<!-- 博客 - 页面布局 > 上中下 -->



<!DOCTYPE html>
<html lang="zh-CN" data-default-color-scheme=dark>
<!-- 博客 - 导航栏上方 -->


<head>
  <meta charset="UTF-8">
  <link rel="apple-touch-icon" sizes="76x76" href="/blog/img/fluid.png">
  <link rel="icon" href="/blog/img/icon/dw.png">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0, shrink-to-fit=no">
  <meta http-equiv="x-ua-compatible" content="ie=edge">
  
  <meta name="theme-color" content="#2f4154">
  <meta name="author" content="Memory">
  <meta name="keywords" content="">

  
    <meta name="description" content="🌮 记录在前端框架使用中的探索过程，享在前端框架使用中遇到的问题以及如何找到解决方案的经验和技巧。">
<meta property="og:type" content="article">
<meta property="og:title" content="浴火重生：从挫败到成功，前端框架的疑难杂症解决之道">
<meta property="og:url" content="https://test.atomgit.net/blog/2023/07/21/%E6%B5%B4%E7%81%AB%E9%87%8D%E7%94%9F%EF%BC%9A%E4%BB%8E%E6%8C%AB%E8%B4%A5%E5%88%B0%E6%88%90%E5%8A%9F%EF%BC%8C%E5%89%8D%E7%AB%AF%E6%A1%86%E6%9E%B6%E7%9A%84%E7%96%91%E9%9A%BE%E6%9D%82%E7%97%87%E8%A7%A3%E5%86%B3%E4%B9%8B%E9%81%93/index.html">
<meta property="og:site_name" content="Memory&#39;s blog">
<meta property="og:description" content="🌮 记录在前端框架使用中的探索过程，享在前端框架使用中遇到的问题以及如何找到解决方案的经验和技巧。">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://test.atomgit.net/blog/img/artical/sky4.jpg">
<meta property="article:published_time" content="2023-07-21T06:12:12.000Z">
<meta property="article:modified_time" content="2025-05-14T13:12:34.000Z">
<meta property="article:author" content="Memory">
<meta property="article:tag" content="经验">
<meta property="article:tag" content="项目">
<meta property="article:tag" content="Vue">
<meta property="article:tag" content="Ant Design Pro">
<meta property="article:tag" content="React">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:image" content="https://test.atomgit.net/blog/img/artical/sky4.jpg">
  
  
  
  <title>浴火重生：从挫败到成功，前端框架的疑难杂症解决之道 - Memory&#39;s blog</title>

  <link  rel="stylesheet" href="https://lib.baomitu.com/twitter-bootstrap/4.6.1/css/bootstrap.min.css" />



  <link  rel="stylesheet" href="https://lib.baomitu.com/github-markdown-css/4.0.0/github-markdown.min.css" />

  <link  rel="stylesheet" href="https://lib.baomitu.com/hint.css/2.7.0/hint.min.css" />

  <link  rel="stylesheet" href="https://lib.baomitu.com/fancybox/3.5.7/jquery.fancybox.min.css" />



<!-- 主题依赖的图标库，不要自行修改 -->
<!-- Do not modify the link that theme dependent icons -->

<link rel="stylesheet" href="//at.alicdn.com/t/font_1749284_hj8rtnfg7um.css">



<link rel="stylesheet" href="//at.alicdn.com/t/font_1736178_lbnruvf0jn.css">


<link  rel="stylesheet" href="/blog/css/main.css" />


  <link id="highlight-css" rel="stylesheet" href="/blog/css/highlight.css" />
  
    <link id="highlight-css-dark" rel="stylesheet" href="/blog/css/highlight-dark.css" />
  



  
<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.css">



  <script id="fluid-configs">
    var Fluid = window.Fluid || {};
    Fluid.ctx = Object.assign({}, Fluid.ctx)
    var CONFIG = {"hostname":"test.atomgit.net","root":"/blog/","version":"1.9.4","typing":{"enable":true,"typeSpeed":100,"cursorChar":"_","loop":false,"scope":[]},"anchorjs":{"enable":true,"element":"h1,h2,h3,h4,h5,h6","placement":"left","visible":"hover","icon":""},"progressbar":{"enable":true,"height_px":3,"color":"#29d","options":{"showSpinner":false,"trickleSpeed":100}},"code_language":{"enable":true,"default":"TEXT"},"copy_btn":true,"image_caption":{"enable":true},"image_zoom":{"enable":true,"img_url_replace":["",""]},"toc":{"enable":true,"placement":"right","headingSelector":"h1,h2,h3,h4,h5,h6","collapseDepth":0},"lazyload":{"enable":false,"loading_img":"/img/loading.gif","onlypost":false,"offset_factor":2},"web_analytics":{"enable":true,"follow_dnt":true,"baidu":null,"google":null,"gtag":null,"tencent":{"sid":null,"cid":null},"woyaola":null,"cnzz":null,"leancloud":{"appId":"T1hUHH9Ks1ggG9DBE3HgUPpV-gzGzoHsz","appKey":"XFkgzzvzNo3J3uNCbBiSOFKc","server_url":"https://t1huhh9k.lc-cn-n1-shared.com","path":"window.location.pathname","ignore_local":false}},"search_path":"/blog/local-search.xml"};

    if (CONFIG.web_analytics.follow_dnt) {
      var dntVal = navigator.doNotTrack || window.doNotTrack || navigator.msDoNotTrack;
      Fluid.ctx.dnt = dntVal && (dntVal.startsWith('1') || dntVal.startsWith('yes') || dntVal.startsWith('on'));
    }
  </script>
  <script  src="/blog/js/utils.js" ></script>
  <script  src="/blog/js/color-schema.js" ></script>
  

  

  

  

  

  

  

  



  
<meta name="generator" content="Hexo 5.4.2"></head>

<body>
  

  <header>
    <!-- 博客 - 导航栏上方 -->


<div class="header-inner" style="height: 100vh">
  <nav id="navbar" class="navbar fixed-top  navbar-expand-lg navbar-dark scrolling-navbar">
  <div class="container">
    <a class="navbar-brand" href="/blog/">
      <strong>Memory&#39;s blog</strong>
    </a>

    <button id="navbar-toggler-btn" class="navbar-toggler" type="button" data-toggle="collapse"
            data-target="#navbarSupportedContent"
            aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
      <div class="animated-icon"><span></span><span></span><span></span></div>
    </button>

    <!-- Collapsible content -->
    <div class="collapse navbar-collapse" id="navbarSupportedContent">
      <ul class="navbar-nav ml-auto text-center">
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/blog/">
                <i class="iconfont icon-home-fill"></i>
                <span>首页</span>
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/blog/archives/">
                <i class="iconfont icon-archive-fill"></i>
                <span>归档</span>
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/blog/categories/">
                <i class="iconfont icon-category-fill"></i>
                <span>分类</span>
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/blog/tags/">
                <i class="iconfont icon-tags-fill"></i>
                <span>标签</span>
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/blog/about/">
                <i class="iconfont icon-user-fill"></i>
                <span>关于</span>
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/blog/links/">
                <i class="iconfont icon-link-fill"></i>
                <span>友链</span>
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/blog/playlist/">
                <i class="iconfont icon-music"></i>
                <span>音乐</span>
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/blog/Memos/">
                <i class="iconfont icon-comment "></i>
                <span>说说</span>
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/blog/App/">
                <i class="iconfont icon-mobile"></i>
                <span>咫尺</span>
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item dropdown">
              <a class="nav-link dropdown-toggle" target="_self" href="javascript:;" role="button"
                 data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                <i class="iconfont icon-books"></i>
                <span>青简</span>
              </a>
              <div class="dropdown-menu" aria-labelledby="navbarDropdown">
                
                  
                  
                  
                  <a class="dropdown-item" target="_blank" rel="noopener" href="http://47.93.135.62:5230/explore">
                    <i class="iconfont icon-images"></i>
                    <span>碎念微光</span>
                  </a>
                
                  
                  
                  
                  <a class="dropdown-item" href="/blog/New/">
                    <i class="iconfont icon-bug"></i>
                    <span>匠册详析</span>
                  </a>
                
                  
                  
                  
                  <a class="dropdown-item" href="/blog/New/">
                    <i class="iconfont icon-xbox-fill"></i>
                    <span>窗景新编</span>
                  </a>
                
                  
                  
                  
                  <a class="dropdown-item" href="/blog/New/">
                    <i class="iconfont icon-steam"></i>
                    <span>戏码幕后</span>
                  </a>
                
                  
                  
                  
                  <a class="dropdown-item" href="/blog/New/">
                    <i class="iconfont icon-map"></i>
                    <span>他山随拾</span>
                  </a>
                
              </div>
            </li>
          
        
        
            <li class="nav-item" id="search-btn">
                <a class="nav-link" target="_self" href="javascript:;" data-toggle="modal" data-target="#modalNotice" aria-label="Search">
                    <i class="iconfont icon-book"></i>
                    <span>公告</span>
                </a>
            </li>
            
        
        
          <li class="nav-item" id="search-btn">
            <a class="nav-link" target="_self" href="javascript:;" data-toggle="modal" data-target="#modalSearch" aria-label="Search">
              <i class="iconfont icon-search"></i>
            </a>
          </li>
          
        
        
          <li class="nav-item" id="color-toggle-btn">
            <a class="nav-link" target="_self" href="javascript:;" aria-label="Color Toggle">
              <i class="iconfont icon-dark" id="color-toggle-icon"></i>
            </a>
          </li>
        
      </ul>
    </div>
  </div>
</nav>
 
<div id="banner" class="banner" parallax=true
     style="background: url('/blog/img/artical/sky4.jpg') no-repeat center center; background-size: cover;">
  <div class="full-bg-img">

    <div class="mask flex-center" style="background-color: rgba(0, 0, 0, 0.3)">
      <div class="banner-text text-center fade-in-up">

        <div class="h2">
          
            <span id="subtitle" data-typed-text="浴火重生：从挫败到成功，前端框架的疑难杂症解决之道"></span>
          
        </div>


        
          <!-- 文章页面 - 顶部信息 -->

<div class="mt-3">
  
  <span class="post-meta mr-2">
    <i class="iconfont icon-author" aria-hidden="true"></i>
    Memory
  </span>
   
  <span class="post-meta">
    <i class="iconfont icon-date-fill" aria-hidden="true"></i>
    <time datetime="2023-07-21 14:12" pubdate>
      2023年7月21日 下午
    </time>
  </span>
  
</div>

<div class="mt-1">
  
  <span class="post-meta mr-2">
    <i class="iconfont icon-chart"></i>
     48k 字 
  </span>
   
  <span class="post-meta mr-2">
    <i class="iconfont icon-clock-fill"></i>
       120 分钟 
  </span>
     
  <span
    id="leancloud-page-views-container"
    class="post-meta"
    style="display: none"
  >
    <i class="iconfont icon-eye" aria-hidden="true"></i>
    <span id="leancloud-page-views"></span> 次
  </span>

    
</div>


        

        <!-- 添加网站运行时间 -->
        <div class="footer-content" style="background-color: transparent;">
          <div>
            <span id="timeDate"></span>
            <span id="times"></span>
            <script>
            var now = new Date();
            function createtime(){
                var grt= new Date("03/07/2023 00:00:00");//此处修改你的建站时间或者网站上线时间
                now.setTime(now.getTime()+250);
                days = (now - grt ) / 1000 / 60 / 60 / 24;
                dnum = Math.floor(days);
                hours = (now - grt ) / 1000 / 60 / 60 - (24 * dnum);
                hnum = Math.floor(hours);
                if(String(hnum).length ==1 ){
                    hnum = "0" + hnum;
                }
                minutes = (now - grt ) / 1000 /60 - (24 * 60 * dnum) - (60 * hnum);
                mnum = Math.floor(minutes);
                if(String(mnum).length ==1 ){
                          mnum = "0" + mnum;
                }
                seconds = (now - grt ) / 1000 - (24 * 60 * 60 * dnum) - (60 * 60 * hnum) - (60 * mnum);
                snum = Math.round(seconds);
                if(String(snum).length ==1 ){
                          snum = "0" + snum;
                }
                document.getElementById("timeDate").innerHTML = "🚀 &nbsp"+dnum+"&nbsp天";  //此次自定义显示内容
                document.getElementById("times").innerHTML = hnum + "&nbsp小时&nbsp" + mnum + "&nbsp分&nbsp" + snum + "&nbsp秒";
            }  

            if (!window.location.href.includes('/20')) {  
            setInterval("createtime()", 250);  // 只有当URL不包含'specific-page'时，才调用createtime  
            }//此次自定义显示内容
            </script>
          </div>
        </div>

      </div>
      
        <div class="scroll-down-bar">
          <i class="iconfont icon-arrowdown"></i>
        </div>
      
    </div>
  </div>
</div>

</div>

  </header>

  <main>
    
      <!-- 文章页  -->


<div class="container-fluid nopadding-x">

  <div class="row nomargin-x">
    <div class="side-col d-none d-lg-block col-lg-2">
      
  <aside class="sidebar category-bar" style="margin-right: -1rem">
    <!-- 文章页面 - 左边栏所属分类 -->
  

<!-- 文章页 - 文章分类 -->





<div class="category-list">
  
  
    
    
    
    <div class="category row nomargin-x">
      <a class="category-item 
          list-group-item category-item-action col-10 col-md-11 col-xm-11" title="代码锋芒"
        id="heading-843238cb7c4b39b52e95311733ff6da6" role="tab" data-toggle="collapse" href="#collapse-843238cb7c4b39b52e95311733ff6da6"
        aria-expanded="true"
      >
        代码锋芒
        <span class="list-group-count">(31)</span>
        <i class="iconfont icon-arrowright"></i>
      </a>
      
      <div class="category-collapse collapse show" id="collapse-843238cb7c4b39b52e95311733ff6da6"
           role="tabpanel" aria-labelledby="heading-843238cb7c4b39b52e95311733ff6da6">
        
        
          
          
  <div class="category-post-list">
    
    
      
      
        <a href="/blog/2023/03/19/MySQL%E5%AE%89%E8%A3%85%E9%85%8D%E7%BD%AE/" title="MySQL安装配置"
           class="list-group-item list-group-item-action
           ">
          <span class="category-post">MySQL安装配置</span>
        </a>
      
    
      
      
        <a href="/blog/2023/03/22/MySQL%E4%BB%8E%E5%85%A5%E9%97%A8%E5%88%B0%E5%85%A5%E5%9C%9F/" title="MySQL从入门到入土"
           class="list-group-item list-group-item-action
           ">
          <span class="category-post">MySQL从入门到入土</span>
        </a>
      
    
      
      
        <a href="/blog/2023/04/09/Java%E6%B3%9B%E5%9E%8B%E7%9A%84%E7%90%86%E8%A7%A3/" title="Java泛型：赋予灵活性的利器"
           class="list-group-item list-group-item-action
           ">
          <span class="category-post">Java泛型：赋予灵活性的利器</span>
        </a>
      
    
      
      
        <a href="/blog/2023/05/21/%E6%8E%A2%E7%B4%A2%20Python%20%E7%88%AC%E8%99%AB%E7%9A%84%E6%97%A0%E9%99%90%E5%8F%AF%E8%83%BD%E6%80%A7%EF%BC%9A%E5%9F%BA%E7%A1%80%E4%B8%8E%E5%BA%94%E7%94%A8/" title="探索Python爬虫的无限可能性：基础与应用"
           class="list-group-item list-group-item-action
           ">
          <span class="category-post">探索Python爬虫的无限可能性：基础与应用</span>
        </a>
      
    
      
      
        <a href="/blog/2023/06/03/%E4%BB%8E%E9%9B%B6%E5%BC%80%E5%A7%8B%E7%9A%84%20JavaWeb%20%E4%B9%8B%E6%97%85/" title="从零开始的 JavaWeb 之旅"
           class="list-group-item list-group-item-action
           ">
          <span class="category-post">从零开始的 JavaWeb 之旅</span>
        </a>
      
    
      
      
        <a href="/blog/2023/06/10/%E6%95%B0%E6%8D%AE%E5%BA%93-%E5%AE%8C%E6%95%B4%E6%80%A7%E7%BA%A6%E6%9D%9F/" title="数据库-完整性约束"
           class="list-group-item list-group-item-action
           ">
          <span class="category-post">数据库-完整性约束</span>
        </a>
      
    
      
      
        <a href="/blog/2023/06/24/%E4%BD%BF%E7%94%A8%20JSP%20%E6%9E%84%E5%BB%BA%20JavaWeb%20%E9%A1%B9%E7%9B%AE-%E4%BB%A5%E6%95%B0%E6%8D%AE%E5%BA%93%E5%A4%A7%E4%BD%9C%E4%B8%9A%E4%B8%BA%E4%BE%8B/" title="使用JSP构建JavaWeb项目--以数据库大作业为例"
           class="list-group-item list-group-item-action
           ">
          <span class="category-post">使用JSP构建JavaWeb项目--以数据库大作业为例</span>
        </a>
      
    
      
      
        <a href="/blog/2023/07/06/%E6%89%93%E9%80%A0%E6%B5%81%E7%95%85%E7%BC%96%E7%A0%81%E4%B9%8B%E6%97%85%EF%BC%9AIntelliJ%20IDEA%20%E7%9A%84%E9%AB%98%E6%95%88%E4%BD%BF%E7%94%A8%E6%8A%80%E5%B7%A7%E4%B8%8E%E5%B7%A5%E4%BD%9C%E6%B5%81%E7%A8%8B%E4%BC%98%E5%8C%96/" title="打造流畅编码之旅：IntelliJ IDEA 的高效使用技巧与工作流程优化"
           class="list-group-item list-group-item-action
           ">
          <span class="category-post">打造流畅编码之旅：IntelliJ IDEA 的高效使用技巧与工作流程优化</span>
        </a>
      
    
      
      
        <a href="/blog/2023/07/06/%E5%87%A4%E5%87%B0%E6%B6%85%E6%A7%83%EF%BC%9ASpring%20Boot%20%E5%BC%80%E5%8F%91%E4%B9%8B%E8%B7%AF%E4%B8%8A%E7%9A%84%E5%9D%8E%E5%9D%B7%E4%B8%8E%E6%88%90%E9%95%BF/" title="凤凰涅槃：Spring Boot 开发之路上的坎坷与成长"
           class="list-group-item list-group-item-action
           ">
          <span class="category-post">凤凰涅槃：Spring Boot 开发之路上的坎坷与成长</span>
        </a>
      
    
      
      
        <a href="/blog/2023/07/11/%E4%BB%8EIP%E5%88%B0Ping%E5%91%BD%E4%BB%A4%EF%BC%9A%E4%BA%86%E8%A7%A3%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C%E8%BF%9E%E6%8E%A5%E7%9A%84%E5%9F%BA%E7%A1%80/" title="从IP到Ping命令：了解计算机网络连接的基础"
           class="list-group-item list-group-item-action
           ">
          <span class="category-post">从IP到Ping命令：了解计算机网络连接的基础</span>
        </a>
      
    
      
      
        <a href="/blog/categories/%E4%BB%A3%E7%A0%81%E9%94%8B%E8%8A%92/" class="list-group-item list-group-item-action">
          <span class="category-post">More...</span>
        </a>
        
  </div>

          
  
    
    
    
    <div class="category-sub row nomargin-x">
      <a class="category-subitem collapsed
          list-group-item category-item-action col-10 col-md-11 col-xm-11" title="职路星火"
        id="heading-59c550454d1ecf67a2ead26a1c46d14b" role="tab" data-toggle="collapse" href="#collapse-59c550454d1ecf67a2ead26a1c46d14b"
        aria-expanded="false"
      >
        职路星火
        <span class="list-group-count">(2)</span>
        <i class="iconfont icon-arrowright"></i>
      </a>
      
      <div class="category-collapse collapse " id="collapse-59c550454d1ecf67a2ead26a1c46d14b"
           role="tabpanel" aria-labelledby="heading-59c550454d1ecf67a2ead26a1c46d14b">
        
        
          
  <div class="category-post-list">
    
    
      
      
        <a href="/blog/2024/03/07/%E7%A0%BA%E5%89%91%E5%87%BA%E9%9E%98%EF%BC%9A%E6%88%91%E7%9A%84%E8%BD%AF%E4%BB%B6%E5%B7%A5%E7%A8%8B%E5%B8%88%E6%B1%82%E8%81%8C%E4%B9%8B%E6%97%85/" title="砺剑出鞘：我的软件工程师求职之旅"
           class="list-group-item list-group-item-action
           ">
          <span class="category-post">砺剑出鞘：我的软件工程师求职之旅</span>
        </a>
      
    
      
      
        <a href="/blog/2024/04/16/%E6%8B%A8%E4%BA%91%E8%A7%81%E6%97%A5%EF%BC%9A%E8%81%8C%E5%9C%BA%E7%94%9F%E6%B4%BB%E7%9A%84%E7%82%B9%E6%BB%B4%E8%AE%B0%E5%BD%95/" title="拨云见日：职场生活的点滴记录"
           class="list-group-item list-group-item-action
           ">
          <span class="category-post">拨云见日：职场生活的点滴记录</span>
        </a>
      
    
  </div>

        
      </div>
    </div>
  
    
    
    
    <div class="category-sub row nomargin-x">
      <a class="category-subitem collapsed
          list-group-item category-item-action col-10 col-md-11 col-xm-11" title="部署之道"
        id="heading-36acf247b1a64f4bbe423776a392cfde" role="tab" data-toggle="collapse" href="#collapse-36acf247b1a64f4bbe423776a392cfde"
        aria-expanded="false"
      >
        部署之道
        <span class="list-group-count">(5)</span>
        <i class="iconfont icon-arrowright"></i>
      </a>
      
      <div class="category-collapse collapse " id="collapse-36acf247b1a64f4bbe423776a392cfde"
           role="tabpanel" aria-labelledby="heading-36acf247b1a64f4bbe423776a392cfde">
        
        
          
          
  <div class="category-post-list">
    
    
      
      
        <a href="/blog/2023/06/22/Nginx%20%E5%85%A5%E9%97%A8%E6%8C%87%E5%8D%97%EF%BC%9A%E7%90%86%E8%A7%A3%E3%80%81%E9%85%8D%E7%BD%AE%E5%92%8C%E4%BC%98%E5%8C%96/" title="Nginx 入门指南：理解、配置和优化"
           class="list-group-item list-group-item-action
           ">
          <span class="category-post">Nginx 入门指南：理解、配置和优化</span>
        </a>
      
    
      
      
        <a href="/blog/2023/07/11/Docker%20%E5%85%A5%E9%97%A8%E4%B8%8E%E5%AE%9E%E8%B7%B5%EF%BC%9A%E5%BF%AB%E9%80%9F%E6%89%93%E9%80%A0%E9%AB%98%E6%95%88%E7%BD%91%E7%AB%99%E9%83%A8%E7%BD%B2%E7%8E%AF%E5%A2%83/" title="Docker入门与实践：快速打造高效网站部署环境"
           class="list-group-item list-group-item-action
           ">
          <span class="category-post">Docker入门与实践：快速打造高效网站部署环境</span>
        </a>
      
    
      
      
        <a href="/blog/2023/08/17/%E6%B7%B1%E5%85%A5%E7%90%86%E8%A7%A3%20API%20%E7%BD%91%E5%85%B3%EF%BC%9A%E5%8E%9F%E7%90%86%E3%80%81%E5%8A%9F%E8%83%BD%E5%92%8C%E7%94%A8%E9%80%94/" title="深入理解 API 网关：原理、功能和用途"
           class="list-group-item list-group-item-action
           ">
          <span class="category-post">深入理解 API 网关：原理、功能和用途</span>
        </a>
      
    
  </div>

          
  
    
    
    
    <div class="category-sub row nomargin-x">
      <a class="category-subitem collapsed
          list-group-item category-item-action col-10 col-md-11 col-xm-11" title="职路星火"
        id="heading-59c550454d1ecf67a2ead26a1c46d14b" role="tab" data-toggle="collapse" href="#collapse-59c550454d1ecf67a2ead26a1c46d14b"
        aria-expanded="false"
      >
        职路星火
        <span class="list-group-count">(2)</span>
        <i class="iconfont icon-arrowright"></i>
      </a>
      
      <div class="category-collapse collapse " id="collapse-59c550454d1ecf67a2ead26a1c46d14b"
           role="tabpanel" aria-labelledby="heading-59c550454d1ecf67a2ead26a1c46d14b">
        
        
          
  <div class="category-post-list">
    
    
      
      
        <a href="/blog/2024/12/16/%E6%BC%AB%E6%BC%AB%E5%BE%81%E9%80%94%EF%BC%9A%E7%AD%91%E6%A2%A6%E4%BA%8E%E8%81%8C%E5%9C%BA%E9%A3%8E%E9%9B%A8%EF%BC%8C%E5%90%9F%E5%92%8F%E4%BA%8E%E6%97%A5%E5%B8%B8%E8%AF%97%E6%84%8F/" title="漫漫征途：筑梦于职场风雨，吟咏于日常诗意"
           class="list-group-item list-group-item-action
           ">
          <span class="category-post">漫漫征途：筑梦于职场风雨，吟咏于日常诗意</span>
        </a>
      
    
      
      
        <a href="/blog/2025/10/23/%E4%BF%9D%E9%A9%BE%E6%8A%A4%E8%88%AA%E2%80%94%E2%80%94%E5%90%8E%E5%8F%B0%E8%BF%90%E7%BB%B4%E8%A7%86%E8%A7%92%E4%B8%8B%E7%9A%84%E9%AB%98%E9%80%9F%E5%85%AC%E8%B7%AF%E2%80%9C%E7%94%9F%E5%91%BD%E7%BA%BF%E2%80%9D/" title="保驾护航——后台运维视角下的高速公路“生命线”"
           class="list-group-item list-group-item-action
           ">
          <span class="category-post">保驾护航——后台运维视角下的高速公路“生命线”</span>
        </a>
      
    
  </div>

        
      </div>
    </div>
  
        
      </div>
    </div>
  
    
    
    
    <div class="category-sub row nomargin-x">
      <a class="category-subitem collapsed
          list-group-item category-item-action col-10 col-md-11 col-xm-11" title="项目志录"
        id="heading-005e56101bc2a873707cb4461a70ded8" role="tab" data-toggle="collapse" href="#collapse-005e56101bc2a873707cb4461a70ded8"
        aria-expanded="false"
      >
        项目志录
        <span class="list-group-count">(1)</span>
        <i class="iconfont icon-arrowright"></i>
      </a>
      
      <div class="category-collapse collapse " id="collapse-005e56101bc2a873707cb4461a70ded8"
           role="tabpanel" aria-labelledby="heading-005e56101bc2a873707cb4461a70ded8">
        
        
          
  <div class="category-post-list">
    
    
      
      
        <a href="/blog/2023/07/30/%E5%B0%8F%E7%A8%8B%E5%BA%8F%E5%BC%80%E5%8F%91%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%AB%EF%BC%9A%E8%B8%A9%E5%9D%91%E6%8C%87%E5%8D%97%E4%B8%8E%E6%8A%80%E5%B7%A7%E6%80%BB%E7%BB%93/" title="小程序开发经验分享：踩坑指南与技巧总结"
           class="list-group-item list-group-item-action
           ">
          <span class="category-post">小程序开发经验分享：踩坑指南与技巧总结</span>
        </a>
      
    
  </div>

        
      </div>
    </div>
  
        
      </div>
    </div>
  
</div>

  </aside>


    </div>

    <div class="col-lg-8 nopadding-x-md">
      <div class="container nopadding-x-md" id="board-ctn">
        <div id="board">
          <article class="post-content mx-auto">
            <!-- SEO header -->
            <h1 style="display: none">浴火重生：从挫败到成功，前端框架的疑难杂症解决之道</h1>
            
              <p class="note note-success">
                
                  
                    本文最后更新于：7 个月前
                  
                
              </p>
            
            
              <div class="markdown-body">
                
                <h1 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h1><h2 id="Ant-Design-Pro"><a href="#Ant-Design-Pro" class="headerlink" title="Ant Design Pro"></a>Ant Design Pro</h2><blockquote>
<p>2023 年 7 月 21 日</p>
</blockquote>
<p>什么是 Ant Design Pro？按我的理解，这是一个前端框架，却又不仅仅是一个前端框架</p>
<p>Ant Design Pro 的语言是 React，它基于 Ant Design 设计体系，提供了丰富的页面模板、组件和功能，非常适合快速搭建前台页面</p>
<p>Ant Design 组件库：<a target="_blank" rel="noopener" href="https://ant.design/components/pagination-cn">分页 Pagination - Ant Design</a></p>
<p>Ant Design Pro 脚手架：<a target="_blank" rel="noopener" href="https://pro.ant.design/zh-CN/docs/overview/">文档总览 - Ant Design Pro</a></p>
<p>下面是比较官方的定义：</p>
<figure class="highlight gauss"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs gauss">Ant <span class="hljs-built_in">Design</span> Pro 是一个开箱即用的企业级中后台前端/设计解决方案，基于 Ant <span class="hljs-built_in">Design</span> 设计体系，内置了丰富的页面模板、组件和功能，旨在帮助开发者快速搭建企业级中后台应用。<br></code></pre></td></tr></table></figure>

<figure class="highlight gauss"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs gauss">Ant <span class="hljs-built_in">Design</span> Pro 提供了完整的前端开发工作流和最佳实践，具有以下特点和优势：<br>	<span class="hljs-number">1.</span>高度定制化：Ant <span class="hljs-built_in">Design</span> Pro 提供了可灵活配置的模板，可以根据项目需求自定义布局和功能，非常适合快速定制企业级应用。<br>	<span class="hljs-number">2.</span>丰富的模板和组件：Ant <span class="hljs-built_in">Design</span> Pro 内置了多个精心设计的页面模板和丰富的 UI 组件，包括表单、表格、图表、地图等，使开发者可		 以快速构建复杂的中后台应用。<br>	<span class="hljs-number">3.</span>系统化的工作流程：Ant <span class="hljs-built_in">Design</span> Pro 提供了完善的开发工作流程，包括开发环境、测试环境和生产环境的配置、代码检查、测试和构建	   等，使开发者能够便捷地进行前端开发。<br>	<span class="hljs-number">4.</span>功能丰富的插件集成：Ant <span class="hljs-built_in">Design</span> Pro 集成了常用的中后台应用所需的功能，包括菜单权限管理、数据请求、国际化、登录认证等，可       以快速构建完整的、稳定的企业级应用。<br></code></pre></td></tr></table></figure>

<h2 id="Ant-Design-Vue"><a href="#Ant-Design-Vue" class="headerlink" title="Ant Design Vue"></a>Ant Design Vue</h2><blockquote>
<p>2023 年 7 月 21 日</p>
</blockquote>
<p>官网：<a target="_blank" rel="noopener" href="https://www.antdv.com/docs/vue/getting-started-cn">快速上手 - Ant Design Vue (antdv.com)</a></p>
<h2 id="Vite"><a href="#Vite" class="headerlink" title="Vite"></a>Vite</h2><blockquote>
<p>2023 年 7 月 21 日</p>
</blockquote>
<p>官网：<a target="_blank" rel="noopener" href="https://vitejs.cn/guide/why.html">为什么选 Vite | Vite 中文网 (vitejs.cn)</a></p>
<h2 id="写作目标"><a href="#写作目标" class="headerlink" title="写作目标"></a>写作目标</h2><blockquote>
<p>2023 年 7 月 21 日</p>
</blockquote>
<p>脚手架的搭建固然简单，在脚手架的基础上，我们可以更方便地改造代码、对接后端代码、编写我们自己的业务逻辑</p>
<p>但前提是我们要理清框架的目录结构，以及相关的逻辑代码</p>
<p>Ant Design Pro 内置了独特的登录页面、欢迎页面、表格页面，我们要理清登录校验逻辑、发送请求到自己的后端接口、重定向到 login 页的逻辑、管理员校验、页面路由配置等等，这些都是必须熟练掌握的</p>
<p>参考官网：<a target="_blank" rel="noopener" href="https://pro.ant.design/zh-CN/docs/development">启动项目 - Ant Design Pro</a></p>
<p>将来开发个人网站，或者开发个人项目，都可以基于 Ant Design Pro 框架，更快捷、更高效</p>
<h1 id="正文"><a href="#正文" class="headerlink" title="正文"></a>正文</h1><h2 id="JS-基础"><a href="#JS-基础" class="headerlink" title="JS 基础"></a>JS 基础</h2><p>推荐阅读：</p>
<h2 id="Vite-1"><a href="#Vite-1" class="headerlink" title="Vite"></a>Vite</h2><h3 id="开发思路"><a href="#开发思路" class="headerlink" title="开发思路"></a>开发思路</h3><ul>
<li><h5 id="使用-vite-工具快速构建-Vue-开发框架来从零开发，要做什么？一定是做到以下几点：（2023-08-01-午）"><a href="#使用-vite-工具快速构建-Vue-开发框架来从零开发，要做什么？一定是做到以下几点：（2023-08-01-午）" class="headerlink" title="使用 vite 工具快速构建 Vue 开发框架来从零开发，要做什么？一定是做到以下几点：（2023/08/01 午）"></a>使用 vite 工具快速构建 Vue 开发框架来从零开发，要做什么？一定是做到以下几点：（2023/08/01 午）</h5><ul>
<li><h5 id="vite-快速构建框架，启动项目"><a href="#vite-快速构建框架，启动项目" class="headerlink" title="vite 快速构建框架，启动项目"></a>vite 快速构建框架，启动项目</h5></li>
<li><h5 id="配置启动端口"><a href="#配置启动端口" class="headerlink" title="配置启动端口"></a>配置启动端口</h5></li>
<li><h5 id="全局-axios-配置，开发全局请求拦截和相应拦截器，做好跨域请求处理"><a href="#全局-axios-配置，开发全局请求拦截和相应拦截器，做好跨域请求处理" class="headerlink" title="全局 axios 配置，开发全局请求拦截和相应拦截器，做好跨域请求处理"></a>全局 axios 配置，开发全局请求拦截和相应拦截器，做好跨域请求处理</h5></li>
</ul>
</li>
</ul>
<h3 id="快速搭建"><a href="#快速搭建" class="headerlink" title="快速搭建"></a>快速搭建</h3><ul>
<li><h5 id="官网：开始-Vite-官方中文文档-vitejs-dev"><a href="#官网：开始-Vite-官方中文文档-vitejs-dev" class="headerlink" title="官网：开始 | Vite 官方中文文档 (vitejs.dev)"></a>官网：<a target="_blank" rel="noopener" href="https://cn.vitejs.dev/guide/">开始 | Vite 官方中文文档 (vitejs.dev)</a></h5></li>
<li><h5 id="使用-vite-构建工具快速构建-Vue-框架："><a href="#使用-vite-构建工具快速构建-Vue-框架：" class="headerlink" title="使用 vite 构建工具快速构建 Vue 框架："></a>使用 vite 构建工具快速构建 Vue 框架：</h5></li>
</ul>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">npm create vite@latest<br></code></pre></td></tr></table></figure>

<ul>
<li><h5 id="cd-进项目目录，安装依赖："><a href="#cd-进项目目录，安装依赖：" class="headerlink" title="cd 进项目目录，安装依赖："></a>cd 进项目目录，安装依赖：</h5></li>
</ul>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">npm install<br></code></pre></td></tr></table></figure>

<ul>
<li><h5 id="修改-tsconfig-json-文件，添加如下配置："><a href="#修改-tsconfig-json-文件，添加如下配置：" class="headerlink" title="修改 tsconfig.json 文件，添加如下配置："></a>修改 tsconfig.json 文件，添加如下配置：</h5></li>
</ul>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-string">&quot;moduleResolution&quot;</span>: <span class="hljs-string">&quot;Node&quot;</span>,<br></code></pre></td></tr></table></figure>

<ul>
<li><h5 id="如果依赖安装失败，可能是-npm-镜像源的问题，两种解决方法："><a href="#如果依赖安装失败，可能是-npm-镜像源的问题，两种解决方法：" class="headerlink" title="如果依赖安装失败，可能是 npm 镜像源的问题，两种解决方法："></a>如果依赖安装失败，可能是 npm 镜像源的问题，两种解决方法：</h5><ul>
<li><h5 id="修改镜像源：淘宝镜像-gt-官方镜像"><a href="#修改镜像源：淘宝镜像-gt-官方镜像" class="headerlink" title="修改镜像源：淘宝镜像 -&gt; 官方镜像"></a>修改镜像源：淘宝镜像 -&gt; 官方镜像</h5></li>
</ul>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">npm <span class="hljs-built_in">set</span> registry https://registry.npmjs.org/<br></code></pre></td></tr></table></figure>

<ul>
<li><h5 id="使用-yarn-包管理工具："><a href="#使用-yarn-包管理工具：" class="headerlink" title="使用 yarn 包管理工具："></a>使用 yarn 包管理工具：</h5></li>
</ul>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">yarn install<br></code></pre></td></tr></table></figure></li>
<li><h5 id="启动项目：（2023-08-01-早）"><a href="#启动项目：（2023-08-01-早）" class="headerlink" title="启动项目：（2023/08/01 早）"></a>启动项目：（2023/08/01 早）</h5></li>
</ul>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">npm run dev<br></code></pre></td></tr></table></figure>

<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">yarn dev<br></code></pre></td></tr></table></figure>

<h3 id="启动端口"><a href="#启动端口" class="headerlink" title="启动端口"></a>启动端口</h3><p><a target="_blank" rel="noopener" href="https://blog.csdn.net/weixin_41823246/article/details/139950643">vite+vue3 项目修改启动的端口号为 localhost_vue3 端口号在哪里改-CSDN 博客</a></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs javascript"><span class="hljs-comment">// https://vitejs.dev/config/</span><br><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-title function_">defineConfig</span>(&#123;<br>  <span class="hljs-attr">plugins</span>: [<span class="hljs-title function_">vue</span>()],<br>  <span class="hljs-attr">server</span>: &#123;<br>    <span class="hljs-attr">port</span>: <span class="hljs-number">7073</span>, <span class="hljs-comment">// 修改为你想要的端口号</span><br>  &#125;,<br>&#125;);<br></code></pre></td></tr></table></figure>

<h3 id="全局-axios-配置"><a href="#全局-axios-配置" class="headerlink" title="全局 axios 配置"></a>全局 axios 配置</h3><ul>
<li><h5 id="全局安装-axios："><a href="#全局安装-axios：" class="headerlink" title="全局安装 axios："></a>全局安装 axios：</h5></li>
</ul>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">npm install axios<br></code></pre></td></tr></table></figure>

<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">yarn add axios<br></code></pre></td></tr></table></figure>

<ul>
<li><h5 id="在指定目录下封装全局请求-响应拦截器："><a href="#在指定目录下封装全局请求-响应拦截器：" class="headerlink" title="在指定目录下封装全局请求/响应拦截器："></a>在指定目录下封装全局请求/响应拦截器：</h5></li>
</ul>
<figure class="highlight tsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><code class="hljs tsx"><span class="hljs-keyword">import</span> axios <span class="hljs-keyword">from</span> <span class="hljs-string">&quot;axios&quot;</span>;<br><br><span class="hljs-comment">// 创建 Axios 实例</span><br><span class="hljs-keyword">const</span> myAxios = axios.<span class="hljs-title function_">create</span>(&#123;<br>  <span class="hljs-attr">baseURL</span>: <span class="hljs-string">&quot;http://localhost:8083/api&quot;</span>, <span class="hljs-comment">// 设置请求的基础URL</span><br>  <span class="hljs-attr">withCredentials</span>: <span class="hljs-literal">true</span>,<br>&#125;);<br><br><span class="hljs-comment">// 处理请求拦截器</span><br>myAxios.<span class="hljs-property">interceptors</span>.<span class="hljs-property">request</span>.<span class="hljs-title function_">use</span>(<br>  <span class="hljs-function">(<span class="hljs-params">config</span>) =&gt;</span> &#123;<br>    <span class="hljs-comment">// 在请求发送之前做一些处理</span><br>    <span class="hljs-keyword">return</span> config;<br>  &#125;,<br>  <span class="hljs-function">(<span class="hljs-params">error</span>) =&gt;</span> &#123;<br>    <span class="hljs-comment">// 发送请求错误时的处理</span><br>    <span class="hljs-keyword">return</span> <span class="hljs-title class_">Promise</span>.<span class="hljs-title function_">reject</span>(error);<br>  &#125;<br>);<br><br><span class="hljs-comment">// 处理响应拦截器</span><br>myAxios.<span class="hljs-property">interceptors</span>.<span class="hljs-property">response</span>.<span class="hljs-title function_">use</span>(<br>  <span class="hljs-function">(<span class="hljs-params">response</span>) =&gt;</span> &#123;<br>    <span class="hljs-comment">// 对响应数据做处理</span><br>    <span class="hljs-keyword">return</span> response.<span class="hljs-property">data</span>;<br>  &#125;,<br>  <span class="hljs-function">(<span class="hljs-params">error</span>) =&gt;</span> &#123;<br>    <span class="hljs-comment">// 响应错误时的处理</span><br>    <span class="hljs-keyword">return</span> <span class="hljs-title class_">Promise</span>.<span class="hljs-title function_">reject</span>(error);<br>  &#125;<br>);<br><br><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> myAxios;<br></code></pre></td></tr></table></figure>

<h3 id="组件样式-BUG"><a href="#组件样式-BUG" class="headerlink" title="组件样式 BUG"></a>组件样式 BUG</h3><ul>
<li><h5 id="在做-Memory-伙伴匹配时，一直有一个问题困扰着我：组件样式有问题"><a href="#在做-Memory-伙伴匹配时，一直有一个问题困扰着我：组件样式有问题" class="headerlink" title="在做 Memory-伙伴匹配时，一直有一个问题困扰着我：组件样式有问题"></a>在做 Memory-伙伴匹配时，一直有一个问题困扰着我：组件样式有问题</h5></li>
<li><h5 id="这次使用-Vue-从零开发壁纸网站时，终于彻查了这个不起眼的问题："><a href="#这次使用-Vue-从零开发壁纸网站时，终于彻查了这个不起眼的问题：" class="headerlink" title="这次使用 Vue 从零开发壁纸网站时，终于彻查了这个不起眼的问题："></a>这次使用 Vue 从零开发壁纸网站时，终于彻查了这个不起眼的问题：</h5></li>
</ul>
<figure class="highlight tsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs tsx"><span class="hljs-keyword">import</span> &#123; createApp &#125; <span class="hljs-keyword">from</span> <span class="hljs-string">&quot;vue&quot;</span>;<br><span class="hljs-keyword">import</span> <span class="hljs-string">&quot;vant/lib/index.css&quot;</span>;<br><span class="hljs-keyword">import</span> <span class="hljs-title class_">Vant</span> <span class="hljs-keyword">from</span> <span class="hljs-string">&quot;vant&quot;</span>;<br><span class="hljs-keyword">import</span> <span class="hljs-title class_">App</span> <span class="hljs-keyword">from</span> <span class="hljs-string">&quot;./App.vue&quot;</span>;<br><br><span class="hljs-title function_">createApp</span>(<span class="hljs-title class_">App</span>).<span class="hljs-title function_">use</span>(<span class="hljs-title class_">Vant</span>).<span class="hljs-title function_">mount</span>(<span class="hljs-string">&quot;#app&quot;</span>);<br></code></pre></td></tr></table></figure>

<ul>
<li><h5 id="没错，只需在-main-ts-下，引入-“vant-lib-index-css”-样式即可（2023-08-02-早）"><a href="#没错，只需在-main-ts-下，引入-“vant-lib-index-css”-样式即可（2023-08-02-早）" class="headerlink" title="没错，只需在 main.ts 下，引入 “vant/lib/index.css” 样式即可（2023/08/02 早）"></a>没错，只需在 main.ts 下，引入 “vant/lib/index.css” 样式即可（2023/08/02 早）</h5></li>
</ul>
<h3 id="请求头设置无效"><a href="#请求头设置无效" class="headerlink" title="请求头设置无效"></a>请求头设置无效</h3><ul>
<li><h5 id="这个真恶心到我了，POST-请求的请求头设置无效（2023-08-01-晚）"><a href="#这个真恶心到我了，POST-请求的请求头设置无效（2023-08-01-晚）" class="headerlink" title="这个真恶心到我了，POST 请求的请求头设置无效（2023/08/01 晚）"></a>这个真恶心到我了，POST 请求的请求头设置无效（2023/08/01 晚）</h5></li>
<li><h5 id="本来是打算做一个前端上传图片文件，后端接收的功能，但这涉及到前端如何发送，后端如何接收的问题"><a href="#本来是打算做一个前端上传图片文件，后端接收的功能，但这涉及到前端如何发送，后端如何接收的问题" class="headerlink" title="本来是打算做一个前端上传图片文件，后端接收的功能，但这涉及到前端如何发送，后端如何接收的问题"></a>本来是打算做一个前端上传图片文件，后端接收的功能，但这涉及到前端如何发送，后端如何接收的问题</h5></li>
<li><h5 id="做了大量的尝试，只有这种方法，才能在后端正常接收到图片文件："><a href="#做了大量的尝试，只有这种方法，才能在后端正常接收到图片文件：" class="headerlink" title="做了大量的尝试，只有这种方法，才能在后端正常接收到图片文件："></a>做了大量的尝试，只有这种方法，才能在后端正常接收到图片文件：</h5></li>
</ul>
<figure class="highlight tsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><code class="hljs tsx"><span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> myAxios<br>  .<span class="hljs-title function_">post</span>(<span class="hljs-string">&quot;/wallpaper/upload&quot;</span>, file, &#123;<br>    <span class="hljs-attr">headers</span>: &#123;<br>      <span class="hljs-string">&quot;Content-Type&quot;</span>: <span class="hljs-string">&quot;multipart/form-data&quot;</span>,<br>    &#125;,<br>  &#125;)<br>  .<span class="hljs-title function_">then</span>(<span class="hljs-keyword">function</span> (<span class="hljs-params">response</span>) &#123;<br>    <span class="hljs-keyword">if</span> (response.<span class="hljs-property">data</span>) &#123;<br>      <span class="hljs-keyword">return</span> response.<span class="hljs-property">data</span>;<br>    &#125;<br>  &#125;)<br>  .<span class="hljs-title function_">catch</span>(<span class="hljs-keyword">function</span> (<span class="hljs-params">error</span>) &#123;<br>    <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(error);<br>  &#125;);<br></code></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@PostMapping(&quot;/upload&quot;)</span><br>  <span class="hljs-keyword">public</span> String <span class="hljs-title function_">uploadFile</span><span class="hljs-params">(<span class="hljs-meta">@RequestParam(&quot;file&quot;)</span> MultipartFile file)</span> &#123;<br>      <span class="hljs-keyword">if</span> (file.isEmpty()) &#123;<br>          <span class="hljs-keyword">return</span> <span class="hljs-string">&quot;上传的文件为空&quot;</span>;<br>      &#125;<br><br>      <span class="hljs-comment">// 处理上传的文件</span><br>      <span class="hljs-keyword">try</span> &#123;<br>          <span class="hljs-type">byte</span>[] bytes = file.getBytes();<br>          <span class="hljs-comment">// 可以选择保存文件到服务器的指定路径</span><br>          <span class="hljs-comment">// Files.write(Paths.get(&quot;文件保存路径&quot;), bytes);</span><br><br>          <span class="hljs-comment">// 在这里可以根据需要进行相关的业务逻辑处理</span><br><br>          <span class="hljs-keyword">return</span> <span class="hljs-string">&quot;文件上传成功&quot;</span>;<br>      &#125; <span class="hljs-keyword">catch</span> (IOException e) &#123;<br>          e.printStackTrace();<br>      &#125;<br>      <span class="hljs-keyword">return</span> <span class="hljs-string">&quot;文件上传失败&quot;</span>;<br>  &#125;<br></code></pre></td></tr></table></figure>

<blockquote>
<p>2024 年 8 月 22 日</p>
</blockquote>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/CYK_byte/article/details/133856894">Vue 网络处理 - axios 异步请求的使用，请求响应拦截器（最佳实践）_vue axios-CSDN 博客</a></p>
<h2 id="Ant-Design-Pro-1"><a href="#Ant-Design-Pro-1" class="headerlink" title="Ant Design Pro"></a>Ant Design Pro</h2><h3 id="快速搭建-1"><a href="#快速搭建-1" class="headerlink" title="快速搭建"></a>快速搭建</h3><ul>
<li><h5 id="官网：开始使用-Ant-Design-Pro"><a href="#官网：开始使用-Ant-Design-Pro" class="headerlink" title="官网：开始使用 - Ant Design Pro"></a>官网：<a target="_blank" rel="noopener" href="https://pro.ant.design/zh-CN/docs/getting-started">开始使用 - Ant Design Pro</a></h5></li>
<li><h5 id="我们可以按以下步骤，快速搭建-Ant-Design-Pro-脚手架："><a href="#我们可以按以下步骤，快速搭建-Ant-Design-Pro-脚手架：" class="headerlink" title="我们可以按以下步骤，快速搭建 Ant Design Pro 脚手架："></a>我们可以按以下步骤，快速搭建 Ant Design Pro 脚手架：</h5></li>
<li><h5 id="在正确安装-Node-js-环境下的前提下，依次执行以下命令："><a href="#在正确安装-Node-js-环境下的前提下，依次执行以下命令：" class="headerlink" title="在正确安装 Node.js 环境下的前提下，依次执行以下命令："></a>在正确安装 Node.js 环境下的前提下，依次执行以下命令：</h5></li>
<li><h5 id="使用-npm-全局安装-pro-cli-构建工具（脚手架）："><a href="#使用-npm-全局安装-pro-cli-构建工具（脚手架）：" class="headerlink" title="使用 npm 全局安装 pro-cli 构建工具（脚手架）："></a>使用 npm 全局安装 pro-cli 构建工具（脚手架）：</h5></li>
</ul>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">npm i @ant-design/pro-cli -g<br></code></pre></td></tr></table></figure>

<ul>
<li><h5 id="使用脚手架，在指定目录下快速搭建前端框架："><a href="#使用脚手架，在指定目录下快速搭建前端框架：" class="headerlink" title="使用脚手架，在指定目录下快速搭建前端框架："></a>使用脚手架，在指定目录下快速搭建前端框架：</h5></li>
</ul>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">pro create memory-api<br></code></pre></td></tr></table></figure>

<p><img src="http://blog.memory-life.xyz/image-20240130210310142.png" alt="image-20240130210310142"></p>
<ul>
<li><h5 id="项目下安装-yarn-包管理工具："><a href="#项目下安装-yarn-包管理工具：" class="headerlink" title="项目下安装 yarn 包管理工具："></a>项目下安装 yarn 包管理工具：</h5></li>
</ul>
<figure class="highlight ebnf"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs ebnf"><span class="hljs-attribute">yarn -V</span><br></code></pre></td></tr></table></figure>

<ul>
<li><h5 id="至此，前端项目框架搭建完成，启动项目：（2023-07-21-晚）"><a href="#至此，前端项目框架搭建完成，启动项目：（2023-07-21-晚）" class="headerlink" title="至此，前端项目框架搭建完成，启动项目：（2023/07/21 晚）"></a>至此，前端项目框架搭建完成，启动项目：（2023/07/21 晚）</h5></li>
</ul>
<figure class="highlight routeros"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs routeros">yarn <span class="hljs-built_in">run</span> start<br></code></pre></td></tr></table></figure>

<h3 id="页面路由报错"><a href="#页面路由报错" class="headerlink" title="页面路由报错"></a>页面路由报错</h3><ul>
<li><h5 id="在-config-routes-ts-下设置好页面路由后，一定要在对应组件下添加-index-tsx-文件："><a href="#在-config-routes-ts-下设置好页面路由后，一定要在对应组件下添加-index-tsx-文件：" class="headerlink" title="在 config/routes.ts 下设置好页面路由后，一定要在对应组件下添加 index.tsx 文件："></a>在 config/routes.ts 下设置好页面路由后，一定要在对应组件下添加 index.tsx 文件：</h5></li>
</ul>
<figure class="highlight tsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs tsx"><span class="hljs-comment">//接口全部详情页</span><br>&#123;<br>  <span class="hljs-attr">name</span>: <span class="hljs-string">&#x27;接口详情&#x27;</span>,<br>  <span class="hljs-attr">icon</span>: <span class="hljs-string">&#x27;user&#x27;</span>,<br>  <span class="hljs-attr">path</span>: <span class="hljs-string">&#x27;/interfaceInfo/info&#x27;</span>,<br>  <span class="hljs-attr">component</span>: <span class="hljs-string">&#x27;./TableList/entireCommend&#x27;</span>,<br>&#125;,<br></code></pre></td></tr></table></figure>

<ul>
<li><h5 id="否则项目启动后会报错：（2023-08-05-晚）"><a href="#否则项目启动后会报错：（2023-08-05-晚）" class="headerlink" title="否则项目启动后会报错：（2023/08/05 晚）"></a>否则项目启动后会报错：（2023/08/05 晚）</h5></li>
</ul>
<p><img src="http://blog.memory-life.xyz/image-20230805233331422.png" alt="image-20230805233331422"></p>
<h3 id="页面路由跳转（1）"><a href="#页面路由跳转（1）" class="headerlink" title="页面路由跳转（1）"></a>页面路由跳转（1）</h3><ul>
<li><h5 id="使用-umi-router-实现路由跳转："><a href="#使用-umi-router-实现路由跳转：" class="headerlink" title="使用 umi/router 实现路由跳转："></a>使用 umi/router 实现路由跳转：</h5></li>
<li><h5 id="官网：在页面间跳转-UmiJS"><a href="#官网：在页面间跳转-UmiJS" class="headerlink" title="官网：在页面间跳转 | UmiJS"></a>官网：<a target="_blank" rel="noopener" href="https://v2.umijs.org/zh/guide/navigate-between-pages.html#%E5%A3%B0%E6%98%8E%E5%BC%8F">在页面间跳转 | UmiJS</a></h5></li>
<li><h5 id="全局安装-umi："><a href="#全局安装-umi：" class="headerlink" title="全局安装 umi："></a>全局安装 umi：</h5></li>
</ul>
<figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs"><br></code></pre></td></tr></table></figure>

<ul>
<li><h5 id="命令式跳转："><a href="#命令式跳转：" class="headerlink" title="命令式跳转："></a>命令式跳转：</h5></li>
</ul>
<figure class="highlight tsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs tsx"><span class="hljs-keyword">import</span> router <span class="hljs-keyword">from</span> <span class="hljs-string">&quot;umi/router&quot;</span>;<br><br><span class="hljs-keyword">function</span> <span class="hljs-title function_">goToListPage</span>(<span class="hljs-params"></span>) &#123;<br>  router.<span class="hljs-title function_">push</span>(<span class="hljs-string">&quot;/list&quot;</span>);<br>&#125;<br></code></pre></td></tr></table></figure>

<ul>
<li><h5 id="声明式跳转：（2023-08-05-晚）"><a href="#声明式跳转：（2023-08-05-晚）" class="headerlink" title="声明式跳转：（2023/08/05 晚）"></a>声明式跳转：（2023/08/05 晚）</h5></li>
</ul>
<figure class="highlight tsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs tsx"><span class="hljs-keyword">import</span> <span class="hljs-title class_">Link</span> <span class="hljs-keyword">from</span> <span class="hljs-string">&quot;umi/link&quot;</span>;<br><br><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> () =&gt; <span class="language-xml"><span class="hljs-tag">&lt;<span class="hljs-name">Link</span> <span class="hljs-attr">to</span>=<span class="hljs-string">&quot;/list&quot;</span>&gt;</span>Go to list page<span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span></span>;<br></code></pre></td></tr></table></figure>

<h3 id="OpenAI-生成接口"><a href="#OpenAI-生成接口" class="headerlink" title="OpenAI 生成接口"></a>OpenAI 生成接口</h3><ul>
<li><h5 id="如何使用-Knif4j-Swagger2-生成请求接口文档，可以参考学习《快速启动：开发自己的定制化-Spring-Boot-项目模板》一文"><a href="#如何使用-Knif4j-Swagger2-生成请求接口文档，可以参考学习《快速启动：开发自己的定制化-Spring-Boot-项目模板》一文" class="headerlink" title="如何使用 Knif4j + Swagger2 生成请求接口文档，可以参考学习《快速启动：开发自己的定制化-Spring-Boot-项目模板》一文"></a>如何使用 Knif4j + Swagger2 生成请求接口文档，可以参考学习《快速启动：开发自己的定制化-Spring-Boot-项目模板》一文</h5></li>
<li><p>官网文档：<a target="_blank" rel="noopener" href="https://doc.xiaominfo.com/">Knife4j · 集 Swagger2 及 OpenAPI3 为一体的增强解决方案. | Knife4j (xiaominfo.com)</a>（2023/08/25 晚）</p>
</li>
<li><h5 id="后端接口文档："><a href="#后端接口文档：" class="headerlink" title="后端接口文档："></a>后端接口文档：</h5></li>
</ul>
<p><img src="http://blog.memory-life.xyz/image-20230809132710999.png" alt="image-20230809132710999"></p>
<ul>
<li>前端 config/config.ts 下的配置：</li>
</ul>
<figure class="highlight tsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs tsx"><span class="hljs-attr">openAPI</span>: [<br>   &#123;<br>     <span class="hljs-attr">requestLibPath</span>: <span class="hljs-string">&quot;import &#123; request &#125; from &#x27;@umijs/max&#x27;&quot;</span>,<br>     <span class="hljs-attr">schemaPath</span>: <span class="hljs-string">&#x27;http://localhost:8104/api/v2/api-docs?group=壁纸分享&#x27;</span>,<br>     <span class="hljs-attr">projectName</span>: <span class="hljs-string">&#x27;pic-memories&#x27;</span>,<br>   &#125;,<br> ],<br></code></pre></td></tr></table></figure>

<ul>
<li><h5 id="执行以下命令，一键生成接口：（2023-08-09-午）"><a href="#执行以下命令，一键生成接口：（2023-08-09-午）" class="headerlink" title="执行以下命令，一键生成接口：（2023/08/09 午）"></a>执行以下命令，一键生成接口：（2023/08/09 午）</h5></li>
</ul>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">npm run openapi<br></code></pre></td></tr></table></figure>

<h3 id="最简页面样式"><a href="#最简页面样式" class="headerlink" title="最简页面样式"></a>最简页面样式</h3><figure class="highlight tsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br></pre></td><td class="code"><pre><code class="hljs tsx"><span class="hljs-keyword">import</span> &#123; listInterfaceInfoByPageUsingPOST &#125; <span class="hljs-keyword">from</span> <span class="hljs-string">&quot;@/services/memory-api/interfaceInfoController&quot;</span>;<br><span class="hljs-keyword">import</span> &#123; <span class="hljs-title class_">ProList</span> &#125; <span class="hljs-keyword">from</span> <span class="hljs-string">&quot;@ant-design/pro-components&quot;</span>;<br><span class="hljs-keyword">import</span> &#123; <span class="hljs-title class_">Button</span>, <span class="hljs-title class_">Space</span> &#125; <span class="hljs-keyword">from</span> <span class="hljs-string">&quot;antd&quot;</span>;<br><span class="hljs-keyword">import</span> <span class="hljs-title class_">React</span>, &#123; useEffect, useState &#125; <span class="hljs-keyword">from</span> <span class="hljs-string">&quot;react&quot;</span>;<br><span class="hljs-keyword">import</span> &#123; useHistory &#125; <span class="hljs-keyword">from</span> <span class="hljs-string">&quot;react-router-dom&quot;</span>;<br><br><span class="hljs-keyword">const</span> <span class="hljs-title class_">InterfaceInfoList</span>: <span class="hljs-title class_">React</span>.<span class="hljs-property">FC</span> = <span class="hljs-function">(<span class="hljs-params">props</span>) =&gt;</span> &#123;<br>  <span class="hljs-keyword">const</span> [interfaceInfo, setInterfaceInfo] = useState&lt;<span class="hljs-variable constant_">API</span>.<span class="hljs-property">InterfaceInfo</span>[]&gt;([]);<br><br>  <span class="hljs-keyword">const</span> <span class="hljs-title function_">fetchData</span> = <span class="hljs-keyword">async</span> (<span class="hljs-params">params: &#123; pageSize?: <span class="hljs-built_in">number</span>; current?: <span class="hljs-built_in">number</span> &#125;</span>) =&gt; &#123;<br>    <span class="hljs-keyword">try</span> &#123;<br>      <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> <span class="hljs-title function_">listInterfaceInfoByPageUsingPOST</span>(&#123;<br>        ...params,<br>      &#125;);<br><br>      <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">&quot;res = &quot;</span> + res.<span class="hljs-property">data</span>?.<span class="hljs-property">records</span>);<br><br>      <span class="hljs-keyword">if</span> (res.<span class="hljs-property">data</span>) &#123;<br>        <span class="hljs-title function_">setInterfaceInfo</span>(res.<span class="hljs-property">data</span>.<span class="hljs-property">records</span>);<br>      &#125;<br><br>      <span class="hljs-comment">// 对返回的数据进行处理</span><br>    &#125; <span class="hljs-keyword">catch</span> (error) &#123;<br>      <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">error</span>(error);<br>    &#125;<br>  &#125;;<br><br>  <span class="hljs-keyword">const</span> history = <span class="hljs-title function_">useHistory</span>();<br>  <span class="hljs-keyword">const</span> <span class="hljs-title function_">handleButtonClick</span> = (<span class="hljs-params"></span>) =&gt; &#123;<br>    <span class="hljs-comment">// 在按钮点击事件中触发页面跳转</span><br>    history.<span class="hljs-title function_">push</span>(<span class="hljs-string">&quot;/TableList/entireCommend&quot;</span>);<br>  &#125;;<br><br>  <span class="hljs-keyword">return</span> (<br>    <span class="hljs-comment">// 页面渲染</span><br>    <span class="hljs-title function_">useEffect</span>(<span class="hljs-function">() =&gt;</span> &#123;<br>      <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">&quot;啊啊啊&quot;</span>);<br>      <span class="hljs-title function_">fetchData</span>(<span class="hljs-number">1</span>, <span class="hljs-number">5</span>);<br>    &#125;, []),<br>    (<br>      <span class="hljs-comment">// 组件的其余部分</span><br>      &lt;<span class="hljs-title class_">ProList</span>&lt;<span class="hljs-built_in">any</span>&gt;<br>        rowKey=<span class="hljs-string">&quot;name&quot;</span><br>        headerTitle=<span class="hljs-string">&quot;基础列表&quot;</span><br>        tooltip=<span class="hljs-string">&quot;基础列表的配置&quot;</span><br>        dataSource=&#123;interfaceInfo&#125;<br>        metas=&#123;&#123;<br>          <span class="hljs-attr">title</span>: &#123;<br>            <span class="hljs-attr">dataIndex</span>: <span class="hljs-string">&quot;name&quot;</span>,<br>          &#125;,<br>          <span class="hljs-attr">description</span>: &#123;<br>            <span class="hljs-attr">dataIndex</span>: <span class="hljs-string">&quot;description&quot;</span>,<br>          &#125;,<br>          <span class="hljs-attr">actions</span>: &#123;<br>            <span class="hljs-attr">render</span>: <span class="hljs-function">(<span class="hljs-params">text, row</span>) =&gt;</span> &#123;<br>              <span class="hljs-keyword">return</span> (<br>                <span class="language-xml"><span class="hljs-tag">&lt;<span class="hljs-name">Space</span>&gt;</span></span><br><span class="language-xml">                  <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span></span><br><span class="language-xml">                    <span class="hljs-tag">&lt;<span class="hljs-name">Button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">&#123;handleButtonClick&#125;</span>&gt;</span>跳转到目标页面<span class="hljs-tag">&lt;/<span class="hljs-name">Button</span>&gt;</span></span><br><span class="language-xml">                  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span><br><span class="language-xml">                <span class="hljs-tag">&lt;/<span class="hljs-name">Space</span>&gt;</span></span><br>              );<br>            &#125;,<br>          &#125;,<br>        &#125;&#125;<br>      /&gt;<br>    )<br>  );<br>&#125;;<br><br><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-title class_">InterfaceInfoList</span>;<br></code></pre></td></tr></table></figure>

<h3 id="改造框架"><a href="#改造框架" class="headerlink" title="改造框架"></a>改造框架</h3><ul>
<li><h5 id="今天我把-API-接口开放平台的前端代码拉下来了，给-PicMemories-做一个管理员后台"><a href="#今天我把-API-接口开放平台的前端代码拉下来了，给-PicMemories-做一个管理员后台" class="headerlink" title="今天我把 API 接口开放平台的前端代码拉下来了，给 PicMemories 做一个管理员后台"></a>今天我把 API 接口开放平台的前端代码拉下来了，给 PicMemories 做一个管理员后台</h5></li>
<li><h5 id="怎么快速改造呢？不要惊慌，做到三点即可：（2023-08-11-晚）"><a href="#怎么快速改造呢？不要惊慌，做到三点即可：（2023-08-11-晚）" class="headerlink" title="怎么快速改造呢？不要惊慌，做到三点即可：（2023/08/11 晚）"></a>怎么快速改造呢？不要惊慌，做到三点即可：（2023/08/11 晚）</h5><ul>
<li>修改接口文档地址，重新生成接口</li>
<li>改造获取用户登录态接口</li>
<li>改造登录接口</li>
<li>改造获取表单信息接口</li>
</ul>
</li>
</ul>
<h3 id="路由配置错误"><a href="#路由配置错误" class="headerlink" title="路由配置错误"></a>路由配置错误</h3><ul>
<li>如果项目启动报如下错误：</li>
</ul>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><code class="hljs bash">PS D:\Project\星球项目\memory-api\memory-api-frontend&gt; yarn start:dev<br>yarn run v1.22.19<br>$ cross-env REACT_APP_ENV=dev MOCK=none UMI_ENV=dev max dev<br>    at Proxy.getRoutes (D:\Project\星球项目\memory-api\memory-api-frontend\node_modules\@umijs\preset-umi\dist\features\tmpFiles\routes.js:61:46)<br>    at Hook.fn (D:\Project\星球项目\memory-api\memory-api-frontend\node_modules\@umijs\preset-umi\dist\features\appData\appData.js:51:35)<br>    at D:\Project\星球项目\memory-api\memory-api-frontend\node_modules\@umijs\core\dist\service\service.js:136:38 &#123;<br>  code: <span class="hljs-string">&#x27;MODULE_NOT_FOUND&#x27;</span><br>&#125;<br>fatal - A complete <span class="hljs-built_in">log</span> of this run can be found <span class="hljs-keyword">in</span>:<br>fatal - D:\Project\星球项目\memory-api\memory-api-frontend\node_modules\.cache\logger\umi.log<br>fatal - Consider reporting a GitHub issue on https://github.com/umijs/umi/issues<br>Done <span class="hljs-keyword">in</span> 3.83s.<br></code></pre></td></tr></table></figure>

<ul>
<li><p>肯定是路由配置错误了，检查检查吧</p>
</li>
<li><h5 id="好像上面的栏目提到过。。（2023-08-16-午）"><a href="#好像上面的栏目提到过。。（2023-08-16-午）" class="headerlink" title="好像上面的栏目提到过。。（2023/08/16 午）"></a>好像上面的栏目提到过。。（2023/08/16 午）</h5></li>
</ul>
<h3 id="可视化数据图表"><a href="#可视化数据图表" class="headerlink" title="可视化数据图表"></a>可视化数据图表</h3><ul>
<li><h5 id="Apache-ECharts：Apache-ECharts"><a href="#Apache-ECharts：Apache-ECharts" class="headerlink" title="Apache ECharts：Apache ECharts"></a>Apache ECharts：<a target="_blank" rel="noopener" href="https://echarts.apache.org/zh/index.html">Apache ECharts</a></h5></li>
<li><h5 id="AntV：AntV-蚂蚁数据可视化"><a href="#AntV：AntV-蚂蚁数据可视化" class="headerlink" title="AntV：AntV | 蚂蚁数据可视化"></a>AntV：<a target="_blank" rel="noopener" href="https://antv.vision/">AntV | 蚂蚁数据可视化</a></h5></li>
<li><h5 id="进入官网，找到相中的图表，在线调试，复制代码：（2023-08-25-晚）"><a href="#进入官网，找到相中的图表，在线调试，复制代码：（2023-08-25-晚）" class="headerlink" title="进入官网，找到相中的图表，在线调试，复制代码：（2023/08/25 晚）"></a>进入官网，找到相中的图表，在线调试，复制代码：（2023/08/25 晚）</h5></li>
</ul>
<p><img src="http://blog.memory-life.xyz/image-20230825204907577.png" alt="image-20230825204907577"></p>
<h3 id="最简页面-2-0"><a href="#最简页面-2-0" class="headerlink" title="最简页面 2.0"></a>最简页面 2.0</h3><ul>
<li>这里再补充一下 React 的最简页面：</li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><code class="hljs react">import &#123;PageContainer&#125; from &#x27;@ant-design/pro-components&#x27;;<br>import &#x27;@umijs/max&#x27;;<br>import ReactECharts from &#x27;echarts-for-react&#x27;;<br>import * as echarts from &#x27;echarts&#x27;;<br><br>/**<br> * 接口分析<br> * @constructor<br> */<br>const testAnalysis: React.FC = () =&gt; &#123;<br>  const option = &#123;&#125;<br><br>  return (<br>    &lt;PageContainer&gt;<br>      &lt;ReactECharts option=&#123;option&#125;/&gt;<br>    &lt;/PageContainer&gt;<br>  );<br>&#125;;<br>export default testAnalysis;<br></code></pre></td></tr></table></figure>

<ul>
<li><p>也就像我这样的前端小白，才会记录这些再简单不过的语法了 😍</p>
</li>
<li><h5 id="呐，直接粘贴代码，看效果就完事了："><a href="#呐，直接粘贴代码，看效果就完事了：" class="headerlink" title="呐，直接粘贴代码，看效果就完事了："></a>呐，直接粘贴代码，看效果就完事了：</h5></li>
</ul>
<p><img src="http://blog.memory-life.xyz/image-20230825205146265.png" alt="image-20230825205146265"></p>
<ul>
<li><h5 id="有时间就学学-React-框架语法了，挺有意思的，到时候总结点东西再记录下-react-的页面开发技巧（2023-08-25-晚）"><a href="#有时间就学学-React-框架语法了，挺有意思的，到时候总结点东西再记录下-react-的页面开发技巧（2023-08-25-晚）" class="headerlink" title="有时间就学学 React 框架语法了，挺有意思的，到时候总结点东西再记录下 react 的页面开发技巧（2023/08/25 晚）"></a>有时间就学学 React 框架语法了，挺有意思的，到时候总结点东西再记录下 react 的页面开发技巧（2023/08/25 晚）</h5></li>
</ul>
<h3 id="区分管理员页面和普通用户页面"><a href="#区分管理员页面和普通用户页面" class="headerlink" title="区分管理员页面和普通用户页面"></a>区分管理员页面和普通用户页面</h3><ul>
<li>在管理员账号下</li>
</ul>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><code class="hljs ts"><span class="hljs-comment">// 管理员</span><br> &#123;<br>   <span class="hljs-attr">path</span>: <span class="hljs-string">&#x27;/&#x27;</span>,<br>   <span class="hljs-attr">access</span>: <span class="hljs-string">&#x27;canAdmin&#x27;</span>,<br>   <span class="hljs-attr">name</span>: <span class="hljs-string">&#x27;admin&#x27;</span>,<br>   <span class="hljs-attr">icon</span>: <span class="hljs-string">&#x27;smile&#x27;</span>,<br>   <span class="hljs-attr">routes</span>: [<br>     <span class="hljs-comment">//用户信息页</span><br>     &#123;<br>       <span class="hljs-attr">name</span>: <span class="hljs-string">&#x27;用户信息&#x27;</span>,<br>       <span class="hljs-attr">access</span>: <span class="hljs-string">&#x27;canAdmin&#x27;</span>,<br>       <span class="hljs-attr">icon</span>: <span class="hljs-string">&#x27;user&#x27;</span>,<br>       <span class="hljs-attr">path</span>: <span class="hljs-string">&#x27;/user/list&#x27;</span>,<br>       <span class="hljs-attr">component</span>: <span class="hljs-string">&#x27;./TableList/Admin/User&#x27;</span>,<br>     &#125;,<br>     <span class="hljs-comment">//接口信息页</span><br>     &#123;<br>       <span class="hljs-attr">name</span>: <span class="hljs-string">&#x27;接口信息&#x27;</span>,<br>       <span class="hljs-attr">access</span>: <span class="hljs-string">&#x27;canAdmin&#x27;</span>,<br>       <span class="hljs-attr">icon</span>: <span class="hljs-string">&#x27;user&#x27;</span>,<br>       <span class="hljs-attr">path</span>: <span class="hljs-string">&#x27;/interfaceInfo/list&#x27;</span>,<br>       <span class="hljs-attr">component</span>: <span class="hljs-string">&#x27;./TableList/Admin/InterfaceInfo&#x27;</span>,<br>     &#125;,<br>     <span class="hljs-comment">// 接口分析页</span><br>     &#123;<br>       <span class="hljs-attr">name</span>: <span class="hljs-string">&#x27;接口分析&#x27;</span>,<br>       <span class="hljs-attr">icon</span>: <span class="hljs-string">&#x27;user&#x27;</span>,<br>       <span class="hljs-attr">path</span>: <span class="hljs-string">&#x27;/admin/interface_analysis&#x27;</span>,<br>       <span class="hljs-attr">component</span>: <span class="hljs-string">&#x27;./TableList/Admin/InterfaceAnalysis&#x27;</span><br>     &#125;,<br><br>   ],<br> &#125;,<br></code></pre></td></tr></table></figure>

<ul>
<li><h5 id="如上，新增了一个二级菜单：管理员页面"><a href="#如上，新增了一个二级菜单：管理员页面" class="headerlink" title="如上，新增了一个二级菜单：管理员页面"></a>如上，新增了一个二级菜单：管理员页面</h5></li>
<li><p>值得注意的是，这里管理员页面默认路由为 /，如果想实现访问 / 跳转至/welcome，则可以这样写：</p>
</li>
</ul>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><code class="hljs ts"> <span class="hljs-comment">//欢迎页</span><br>&#123;<br>   <span class="hljs-attr">path</span>: <span class="hljs-string">&#x27;/welcome&#x27;</span>,<br>   <span class="hljs-attr">name</span>: <span class="hljs-string">&#x27;welcome&#x27;</span>,<br>   <span class="hljs-attr">icon</span>: <span class="hljs-string">&#x27;smile&#x27;</span>,<br>   <span class="hljs-attr">component</span>: <span class="hljs-string">&#x27;./Welcome&#x27;</span>,<br>&#125;,<br><br>&#123;<br>    <span class="hljs-attr">path</span>: <span class="hljs-string">&#x27;/&#x27;</span>,<br>    <span class="hljs-attr">redirect</span>: <span class="hljs-string">&#x27;/welcome&#x27;</span>,<br>&#125;,<br><br> <span class="hljs-comment">// 管理员</span><br>  &#123;<br>    <span class="hljs-attr">path</span>: <span class="hljs-string">&#x27;/&#x27;</span>,<br>    <span class="hljs-attr">access</span>: <span class="hljs-string">&#x27;canAdmin&#x27;</span>,<br>    <span class="hljs-attr">name</span>: <span class="hljs-string">&#x27;admin&#x27;</span>,<br>   ....................<br>  &#125;,<br></code></pre></td></tr></table></figure>

<ul>
<li><h5 id="如上，这里的重定向一定要写在管理员页面路由的前面，这样才能正常跳转至-welcome（2023-09-27-午）"><a href="#如上，这里的重定向一定要写在管理员页面路由的前面，这样才能正常跳转至-welcome（2023-09-27-午）" class="headerlink" title="如上，这里的重定向一定要写在管理员页面路由的前面，这样才能正常跳转至/welcome（2023/09/27 午）"></a>如上，这里的重定向一定要写在管理员页面路由的前面，这样才能正常跳转至/welcome（2023/09/27 午）</h5></li>
</ul>
<h3 id="Prettier-美化配置"><a href="#Prettier-美化配置" class="headerlink" title="Prettier 美化配置"></a>Prettier 美化配置</h3><ul>
<li>配置<strong>生效文件</strong>，以及<strong>快速格式化时</strong>，使用 Prettier 帮助<strong>快速美化代码</strong> <strong>（2023/10/08 早）</strong></li>
</ul>
<p><img src="C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\image-20231008092500820.png" alt="image-20231008092500820"></p>
<h3 id="一条龙完成-Ant-Design-Pro-初始化"><a href="#一条龙完成-Ant-Design-Pro-初始化" class="headerlink" title="一条龙完成 Ant Design Pro 初始化"></a>一条龙完成 Ant Design Pro 初始化</h3><ul>
<li><p>这是一个全新的、思路清晰的框架<strong>优化瘦身一条龙操作技巧</strong>，废话少说，开始<strong>打造自己的前端框架</strong>：</p>
</li>
<li><h5 id="优化瘦身顺序："><a href="#优化瘦身顺序：" class="headerlink" title="优化瘦身顺序："></a>优化瘦身顺序：</h5><ul>
<li><strong>框架初始化</strong>：完成项目的首次构建，能够成功运行项目</li>
<li><strong>框架瘦身</strong>：删除不必要的组件 / 配置，减小框架体量，节省存储空间</li>
<li><strong>框架改造</strong>：<ul>
<li>配置后端接口文档，快速生成后端请求地址</li>
<li>接入后台已开发的登录 / 注册功能（用户登录、获取当前登录用户、管理员权限校验）</li>
</ul>
</li>
</ul>
</li>
<li><p>优化前提：</p>
<ul>
<li><h5 id="后端用户登录、获取当前登录用户、配置允许跨域请求、正确配置接口文档"><a href="#后端用户登录、获取当前登录用户、配置允许跨域请求、正确配置接口文档" class="headerlink" title="后端用户登录、获取当前登录用户、配置允许跨域请求、正确配置接口文档"></a>后端用户登录、获取当前登录用户、配置允许跨域请求、正确配置接口文档</h5></li>
<li><p>请确保以上<strong>接口开发 / 服务配置</strong>已经完成</p>
</li>
</ul>
</li>
</ul>
<h4 id="框架初始化"><a href="#框架初始化" class="headerlink" title="框架初始化"></a>框架初始化</h4><ul>
<li><p>一切按照官方文档来，毕竟前端框架组件更新迭代太快了：</p>
</li>
<li><h5 id="官网：开始使用-Ant-Design-Pro-1"><a href="#官网：开始使用-Ant-Design-Pro-1" class="headerlink" title="官网：开始使用 - Ant Design Pro"></a>官网：<a target="_blank" rel="noopener" href="https://pro.ant.design/zh-CN/docs/getting-started">开始使用 - Ant Design Pro</a></h5></li>
<li><h5 id="现阶段版本，只需依次执行以下命令即可：（2023-10-03-晚）"><a href="#现阶段版本，只需依次执行以下命令即可：（2023-10-03-晚）" class="headerlink" title="现阶段版本，只需依次执行以下命令即可：（2023/10/03 晚）"></a>现阶段版本，只需依次执行以下命令即可：（2023/10/03 晚）</h5></li>
<li><h5 id="使用-npm-全局安装-pro-cli-构建工具（脚手架）：-1"><a href="#使用-npm-全局安装-pro-cli-构建工具（脚手架）：-1" class="headerlink" title="使用 npm 全局安装 pro-cli 构建工具（脚手架）："></a>使用 npm 全局安装 pro-cli 构建工具（脚手架）：</h5></li>
</ul>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">npm i @ant-design/pro-cli -g<br></code></pre></td></tr></table></figure>

<ul>
<li><h5 id="使用脚手架，在指定目录下快速搭建前端框架：-1"><a href="#使用脚手架，在指定目录下快速搭建前端框架：-1" class="headerlink" title="使用脚手架，在指定目录下快速搭建前端框架："></a>使用脚手架，在指定目录下快速搭建前端框架：</h5></li>
</ul>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">pro create memory-api<br></code></pre></td></tr></table></figure>

<ul>
<li><h5 id="项目下安装-yarn-包管理工具：-1"><a href="#项目下安装-yarn-包管理工具：-1" class="headerlink" title="项目下安装 yarn 包管理工具："></a>项目下安装 yarn 包管理工具：</h5></li>
</ul>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">yarn install<br></code></pre></td></tr></table></figure>

<ul>
<li><h5 id="至此，前端项目框架搭建完成，启动项目：（2023-10-03-晚）"><a href="#至此，前端项目框架搭建完成，启动项目：（2023-10-03-晚）" class="headerlink" title="至此，前端项目框架搭建完成，启动项目：（2023/10/03 晚）"></a>至此，前端项目框架搭建完成，启动项目：（2023/10/03 晚）</h5></li>
</ul>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">yarn run start<br></code></pre></td></tr></table></figure>

<h4 id="框架瘦身"><a href="#框架瘦身" class="headerlink" title="框架瘦身"></a>框架瘦身</h4><ul>
<li>删除不需要的代码，减小空间占用</li>
</ul>
<blockquote>
<p>国际化移出<br>mock 移出<br>swagger 移出<br>logo 修改 移出<br>tests types 移出<br>prettier 美化配置<br>jest config 测试框架 删除<br>ds 全局替换 Ant Design Pro / Ant Design</p>
</blockquote>
<h4 id="框架改造"><a href="#框架改造" class="headerlink" title="框架改造"></a>框架改造</h4><blockquote>
<p>登录注册<br>snap login.test 删除<br>删除 lang<br>Subtitle 支持 a 标签 targetblank<br>initial Value 自动登录其他登录 删除<br>手机号登录 全部干掉 删除<br>忘记密码干掉 未登录？去注册<br>传参 userAccount userPassword<br>openApi 快速生成后端请求接口</p>
<p>登录请求 成功返回 失败捕获<br>获取当前登录用户 fetch<br>删除未引用的</p>
<p>保存全局状态<br>只留 current user 改类型<br>改调用方法<br>当前不是登录页面 返回 currenter<br>否则返回空</p>
<p>修改头像 水印<br>前端传递 cokkie<br>修改请求拦截器 直接返回 config<br>注册页面开发</p>
</blockquote>
<ul>
<li><h5 id="Login-页面："><a href="#Login-页面：" class="headerlink" title="Login 页面："></a>Login 页面：</h5></li>
</ul>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><code class="hljs ts"><span class="hljs-keyword">const</span> <span class="hljs-title function_">fetchUserInfo</span> = <span class="hljs-keyword">async</span> (<span class="hljs-params"></span>) =&gt; &#123;<br>  <span class="hljs-keyword">const</span> userInfo = <span class="hljs-keyword">await</span> <span class="hljs-title function_">getLoginUserUsingGET</span>();<br>  <span class="hljs-keyword">if</span> (userInfo) &#123;<br>    <span class="hljs-title function_">flushSync</span>(<span class="hljs-function">() =&gt;</span> &#123;<br>      <span class="hljs-title function_">setInitialState</span>(<span class="hljs-function">(<span class="hljs-params">s</span>) =&gt;</span> (&#123;<br>        ...s,<br>        <span class="hljs-attr">currentUser</span>: userInfo,<br>      &#125;));<br>    &#125;);<br>  &#125;<br>&#125;;<br></code></pre></td></tr></table></figure>

<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><code class="hljs ts"><span class="hljs-keyword">const</span> <span class="hljs-title function_">handleSubmit</span> = <span class="hljs-keyword">async</span> (<span class="hljs-params">values: API.UserLoginRequest</span>) =&gt; &#123;<br>  <span class="hljs-keyword">try</span> &#123;<br>    <span class="hljs-comment">// 登录</span><br>    <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> <span class="hljs-title function_">userLoginUsingPOST</span>(&#123; ...values, <span class="hljs-keyword">type</span> &#125;);<br>    <span class="hljs-keyword">if</span> (res.<span class="hljs-property">code</span> === <span class="hljs-number">0</span>) &#123;<br>      <span class="hljs-keyword">const</span> defaultLoginSuccessMessage = intl.<span class="hljs-title function_">formatMessage</span>(&#123;<br>        <span class="hljs-attr">id</span>: <span class="hljs-string">&quot;pages.login.success&quot;</span>,<br>        <span class="hljs-attr">defaultMessage</span>: <span class="hljs-string">&quot;登录成功！&quot;</span>,<br>      &#125;);<br>      message.<span class="hljs-title function_">success</span>(defaultLoginSuccessMessage);<br>      <span class="hljs-keyword">await</span> <span class="hljs-title function_">fetchUserInfo</span>();<br>      <span class="hljs-keyword">const</span> urlParams = <span class="hljs-keyword">new</span> <span class="hljs-title function_">URL</span>(<span class="hljs-variable language_">window</span>.<span class="hljs-property">location</span>.<span class="hljs-property">href</span>).<span class="hljs-property">searchParams</span>;<br>      history.<span class="hljs-title function_">push</span>(urlParams.<span class="hljs-title function_">get</span>(<span class="hljs-string">&quot;redirect&quot;</span>) || <span class="hljs-string">&quot;/&quot;</span>);<br>      <span class="hljs-keyword">return</span>;<br>    &#125;<br>  &#125; <span class="hljs-keyword">catch</span> (error) &#123;<br>    <span class="hljs-keyword">const</span> defaultLoginFailureMessage = <span class="hljs-string">&quot;登录失败，请重试！&quot;</span>;<br>    <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(error);<br>    message.<span class="hljs-title function_">error</span>(defaultLoginFailureMessage);<br>  &#125;<br>&#125;;<br></code></pre></td></tr></table></figure>

<ul>
<li><h5 id="app-tsx-页面："><a href="#app-tsx-页面：" class="headerlink" title="app.tsx 页面："></a>app.tsx 页面：</h5></li>
</ul>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><code class="hljs ts"><span class="hljs-keyword">export</span> <span class="hljs-keyword">async</span> <span class="hljs-keyword">function</span> <span class="hljs-title function_">getInitialState</span>(<span class="hljs-params"></span>): <span class="hljs-title class_">Promise</span>&lt;&#123;<br>  currentUser?: <span class="hljs-variable constant_">API</span>.<span class="hljs-property">LoginUserVO</span>;<br>&#125;&gt; &#123;<br>  <span class="hljs-keyword">const</span> <span class="hljs-title function_">fetchUserInfo</span> = <span class="hljs-keyword">async</span> (<span class="hljs-params"></span>) =&gt; &#123;<br>    <span class="hljs-keyword">try</span> &#123;<br>      <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> <span class="hljs-title function_">getLoginUserUsingGET</span>(&#123;<br>        <span class="hljs-attr">skipErrorHandler</span>: <span class="hljs-literal">true</span>,<br>      &#125;);<br>      <span class="hljs-keyword">return</span> res.<span class="hljs-property">data</span>;<br>    &#125; <span class="hljs-keyword">catch</span> (error) &#123;<br>      history.<span class="hljs-title function_">push</span>(loginPath);<br>    &#125;<br>    <span class="hljs-keyword">return</span> <span class="hljs-literal">undefined</span>;<br>  &#125;;<br><br>  <span class="hljs-comment">// 如果不是登录页面，执行</span><br>  <span class="hljs-keyword">const</span> &#123; location &#125; = history;<br>  <span class="hljs-keyword">if</span> (location.<span class="hljs-property">pathname</span> !== loginPath) &#123;<br>    <span class="hljs-keyword">const</span> currentUser = <span class="hljs-keyword">await</span> <span class="hljs-title function_">fetchUserInfo</span>();<br>    <span class="hljs-keyword">return</span> &#123;<br>      currentUser,<br>    &#125;;<br>  &#125;<br>  <span class="hljs-keyword">return</span> &#123;&#125;;<br>&#125;<br></code></pre></td></tr></table></figure>

<ul>
<li><h5 id="access-tsx-页面："><a href="#access-tsx-页面：" class="headerlink" title="access.tsx 页面："></a>access.tsx 页面：</h5></li>
</ul>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs ts"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-keyword">function</span> <span class="hljs-title function_">access</span>(<span class="hljs-params"></span><br><span class="hljs-params">  initialState: &#123; currentUser?: API.LoginUserVO &#125; | <span class="hljs-literal">undefined</span></span><br><span class="hljs-params"></span>) &#123;<br>  <span class="hljs-keyword">const</span> &#123; currentUser &#125; = initialState ?? &#123;&#125;;<br>  <span class="hljs-keyword">return</span> &#123;<br>    <span class="hljs-attr">canAdmin</span>: currentUser &amp;&amp; currentUser.<span class="hljs-property">userRole</span> === <span class="hljs-string">&quot;0&quot;</span>,<br>  &#125;;<br>&#125;<br></code></pre></td></tr></table></figure>

<ul>
<li><h5 id="config-ts-页面："><a href="#config-ts-页面：" class="headerlink" title="config.ts 页面："></a>config.ts 页面：</h5></li>
</ul>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs ts"><span class="hljs-attr">openAPI</span>: [<br>   &#123;<br>     <span class="hljs-attr">requestLibPath</span>: <span class="hljs-string">&quot;import &#123; request &#125; from &#x27;@umijs/max&#x27;&quot;</span>,<br>     <span class="hljs-comment">// 或者使用在线的版本</span><br>     <span class="hljs-attr">schemaPath</span>: <span class="hljs-string">&quot;http://localhost:8101/api/v2/api-docs&quot;</span>,<br>     <span class="hljs-attr">projectName</span>: <span class="hljs-string">&#x27;memory-bi&#x27;</span>,<br>     <span class="hljs-attr">mock</span>: <span class="hljs-literal">false</span>,<br>   &#125;,<br> ],<br></code></pre></td></tr></table></figure>

<ul>
<li><h5 id="这里踩了个很恶心的-BUG，执行完成-run-openapi-之后，有些方法调用的路径会发生紊乱："><a href="#这里踩了个很恶心的-BUG，执行完成-run-openapi-之后，有些方法调用的路径会发生紊乱：" class="headerlink" title="这里踩了个很恶心的 BUG，执行完成 run openapi 之后，有些方法调用的路径会发生紊乱："></a>这里踩了个很恶心的 BUG，执行完成 run openapi 之后，有些方法调用的路径会发生紊乱：</h5></li>
</ul>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs javascript"><span class="hljs-keyword">import</span> &#123; outLogin &#125; <span class="hljs-keyword">from</span> <span class="hljs-string">&quot;@//services/ant-design-pro/login&quot;</span>;<br></code></pre></td></tr></table></figure>

<ul>
<li><h5 id="修改调整一番就好了（2023-10-03-晚）"><a href="#修改调整一番就好了（2023-10-03-晚）" class="headerlink" title="修改调整一番就好了（2023/10/03 晚）"></a>修改调整一番就好了（2023/10/03 晚）</h5></li>
</ul>
<h3 id="开发一个页面的步骤"><a href="#开发一个页面的步骤" class="headerlink" title="开发一个页面的步骤"></a>开发一个页面的步骤</h3><ul>
<li><h5 id="创建路由和页面（2023-10-11-晚）"><a href="#创建路由和页面（2023-10-11-晚）" class="headerlink" title="创建路由和页面（2023/10/11 晚）"></a>创建路由和页面（2023/10/11 晚）</h5></li>
<li><p>获取需要的数据，定义 state 变量来存储数据，用于页面展示</p>
</li>
<li><p>先把<strong>最简单</strong>、<strong>最直观</strong>的数据展示给前端，再去调样式</p>
</li>
<li><p>引入 <strong>Ant Design</strong> 的 List 组件，复制示例代码</p>
</li>
<li><p>调整 List 组件中的内容为自己的（注意，获取用户头像可以从初始化状态中获取）</p>
</li>
</ul>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs ts"><span class="hljs-keyword">const</span> &#123; initialState &#125; = <span class="hljs-title function_">useModel</span>(<span class="hljs-string">&quot;@@initialState&quot;</span>);<br><span class="hljs-keyword">const</span> &#123; currentUser &#125; = initialState ?? &#123;&#125;;<br></code></pre></td></tr></table></figure>

<ul>
<li>针对样式，对数据进行一些处理，比如<strong>统一隐藏自身的 title</strong></li>
<li>增加<strong>分页</strong>（<strong>当前页码、每页展示数、总记录数</strong>）、增加<strong>展示列</strong></li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><code class="hljs react">&lt;List<br>        grid=&#123;&#123;<br>          gutter: 16,<br>          xs: 1,<br>          sm: 1,<br>          md: 1,<br>          lg: 2,<br>          xl: 2,<br>          xxl: 2,<br>        &#125;&#125;<br>        itemLayout=&quot;vertical&quot;<br>        size=&quot;large&quot;<br>        pagination=&#123;&#123;<br>          onChange: (page) =&gt; &#123;<br>            setSearchParams(&#123;<br>              ...searchParams,<br>              current: page,<br>            &#125;)<br>          &#125;,<br>          current: searchParams.current,<br>          pageSize: searchParams.pageSize,<br>          total: total,<br>        &#125;&#125;<br>        dataSource=&#123;chartList&#125;<br><br>        ..........................<br>        )&#125;<br>      /&gt;<br></code></pre></td></tr></table></figure>

<ul>
<li>增加<strong>搜索框</strong></li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><code class="hljs react">&lt;Search<br>       className=&quot;margin-bottom-16&quot;<br>       placeholder=&quot;请输入图表名称&quot;<br>       enterButton<br>       loading=&#123;loading&#125;<br>       onSearch=&#123;(value) =&gt; &#123;<br>         // 设置搜索条件<br>         setSearchParams(&#123;<br>           ...initSearchParams,<br>           name: value,<br>         &#125;)<br>       &#125;&#125;/&gt;<br></code></pre></td></tr></table></figure>

<ul>
<li>其他优化：比如<strong>添加 loading 效果</strong></li>
</ul>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs ts"><span class="hljs-keyword">const</span> [loading, setLoading] = useState&lt;<span class="hljs-built_in">boolean</span>&gt;(<span class="hljs-literal">false</span>);<br></code></pre></td></tr></table></figure>

<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><code class="hljs ts"><span class="hljs-keyword">const</span> <span class="hljs-title function_">loadData</span> = <span class="hljs-keyword">async</span> (<span class="hljs-params"></span>) =&gt; &#123;<br>  <span class="hljs-title function_">setLoading</span>(<span class="hljs-literal">true</span>);<br>  <span class="hljs-keyword">try</span> &#123;<br>    <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> <span class="hljs-title function_">listChartByPageUsingPOST</span>(searchParams);<br>    <span class="hljs-keyword">if</span> (res.<span class="hljs-property">data</span>) &#123;<br>      <span class="hljs-comment">// 获取图表列表</span><br>      <span class="hljs-title function_">setChartList</span>(res.<span class="hljs-property">data</span>?.<span class="hljs-property">records</span> ?? []);<br>      <span class="hljs-comment">// 获取总数</span><br>      <span class="hljs-title function_">setTotal</span>(res.<span class="hljs-property">data</span>?.<span class="hljs-property">total</span> ?? <span class="hljs-number">0</span>);<br>      <span class="hljs-comment">// 搜索完成</span><br>      <span class="hljs-title function_">setLoading</span>(<span class="hljs-literal">false</span>);<br>    &#125; <span class="hljs-keyword">else</span> &#123;<br>      message.<span class="hljs-title function_">error</span>(<span class="hljs-string">&quot;获取我的图标失败&quot;</span>);<br>    &#125;<br>  &#125; <span class="hljs-keyword">catch</span> (<span class="hljs-attr">e</span>: <span class="hljs-built_in">any</span>) &#123;<br>    message.<span class="hljs-title function_">error</span>(<span class="hljs-string">&quot;获取我的图标失败&quot;</span> + e.<span class="hljs-property">message</span>);<br>  &#125;<br>&#125;;<br></code></pre></td></tr></table></figure>

<ul>
<li>这里添加了一个 loading 效果，在<strong>执行搜索过程</strong>中（即<strong>按下搜索后，到数据成功返回的时间段</strong>），搜索按钮的<strong>状态为转圈圈</strong></li>
</ul>
<h3 id="模拟低网速运行状态"><a href="#模拟低网速运行状态" class="headerlink" title="模拟低网速运行状态"></a>模拟低网速运行状态</h3><ul>
<li><p>明白上面提到的搜索按钮的 loading 效果后，就应该明白： <strong>（2023/11/11 晚）</strong></p>
</li>
<li><h5 id="只有执行搜索的时间越长，即响应的时间越长时，这个-loading-效果越明显"><a href="#只有执行搜索的时间越长，即响应的时间越长时，这个-loading-效果越明显" class="headerlink" title="只有执行搜索的时间越长，即响应的时间越长时，这个 loading 效果越明显"></a>只有执行搜索的时间越长，即响应的时间越长时，这个 loading 效果越明显</h5></li>
<li><p>那我们就要模拟服务在<strong>低网速状态运行</strong>的状态了，如下：</p>
</li>
</ul>
<p><img src="http://blog.memory-life.xyz/image-20231207235631152.png" alt="image-20231207235631152"></p>
<ul>
<li>选中对应的网络状态，就可以<strong>模仿在该网络环境下发送请求</strong>了 <strong>（2023/12/07 晚）</strong></li>
</ul>
<h3 id="引入外部页面组件"><a href="#引入外部页面组件" class="headerlink" title="引入外部页面组件"></a>引入外部页面组件</h3><ul>
<li>如下，编写页面组件 <code>RandomPoem</code>：</li>
</ul>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><code class="hljs ts"><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * 接口分析</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@constructor</span></span><br><span class="hljs-comment"> */</span><br><span class="hljs-keyword">import</span> &#123;<span class="hljs-title class_">PageContainer</span>&#125; <span class="hljs-keyword">from</span> <span class="hljs-string">&quot;@ant-design/pro-components&quot;</span>;<br><span class="hljs-keyword">import</span> &#123;<span class="hljs-title class_">CaretRightFilled</span>&#125; <span class="hljs-keyword">from</span> <span class="hljs-string">&quot;@ant-design/icons&quot;</span>;<br><span class="hljs-keyword">import</span> &#123;<span class="hljs-title class_">Button</span>, <span class="hljs-title class_">Form</span>, message, <span class="hljs-title class_">Input</span>, <span class="hljs-title class_">Tag</span>, <span class="hljs-title class_">Table</span>&#125; <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;antd&#x27;</span>;<br><span class="hljs-keyword">import</span> &#123;<span class="hljs-title class_">ColumnsType</span>&#125; <span class="hljs-keyword">from</span> <span class="hljs-string">&quot;antd/es/table&quot;</span>;<br><span class="hljs-keyword">import</span> <span class="hljs-title class_">React</span>, &#123;useState&#125; <span class="hljs-keyword">from</span> <span class="hljs-string">&quot;react&quot;</span>;<br><span class="hljs-keyword">import</span> initialState <span class="hljs-keyword">from</span> <span class="hljs-string">&quot;@@/plugin-initialState/@@initialState&quot;</span>;<br><span class="hljs-keyword">import</span> &#123;invokeInterfaceInfoUsingPOST&#125; <span class="hljs-keyword">from</span> <span class="hljs-string">&quot;@/services/memory-api/interfaceInfoController&quot;</span>;<br><span class="hljs-keyword">import</span> &#123;useParams&#125; <span class="hljs-keyword">from</span> <span class="hljs-string">&quot;@@/exports&quot;</span>;<br><br><span class="hljs-keyword">const</span> <span class="hljs-title class_">RandomPoem</span>: <span class="hljs-title class_">React</span>.<span class="hljs-property">FC</span> = <span class="hljs-function">() =&gt;</span> &#123;<br>.....................<br><br>  <span class="hljs-keyword">return</span> (<br>    <span class="language-xml"><span class="hljs-tag">&lt;<span class="hljs-name">PageContainer</span>&gt;</span></span><br><span class="language-xml">      .....................</span><br><span class="language-xml">    <span class="hljs-tag">&lt;/<span class="hljs-name">PageContainer</span>&gt;</span></span><br>  );<br>&#125;;<br><br><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-title class_">RandomPoem</span>;<br></code></pre></td></tr></table></figure>

<p><img src="C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\image-20231207235417783.png" alt="image-20231207235417783"></p>
<ul>
<li>在需要引入该组件的页面导入该组件，并引入：</li>
</ul>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs ts"><span class="hljs-keyword">import</span> <span class="hljs-title class_">RandomPoem</span> <span class="hljs-keyword">from</span> <span class="hljs-string">&quot;@/pages/TableList/InterfaceInfo/RandomPoem&quot;</span>;<br></code></pre></td></tr></table></figure>

<p><img src="http://blog.memory-life.xyz/image-20231207235457463.png" alt="image-20231207235457463"></p>
<h2 id="Ant-Design-Vue-1"><a href="#Ant-Design-Vue-1" class="headerlink" title="Ant Design Vue"></a>Ant Design Vue</h2><ul>
<li><p>官网：<a target="_blank" rel="noopener" href="https://2x.antdv.com/docs/vue/getting-started-cn">Ant Design Vue (antdv.com)</a></p>
</li>
<li><h5 id="以下仅为开发过程中的个人经验总结，不具备教学价值，本人主-Java-后端，前端框架使用很不熟练-（2023-08-27-早）"><a href="#以下仅为开发过程中的个人经验总结，不具备教学价值，本人主-Java-后端，前端框架使用很不熟练-（2023-08-27-早）" class="headerlink" title="以下仅为开发过程中的个人经验总结，不具备教学价值，本人主 Java 后端，前端框架使用很不熟练~（2023/08/27 早）"></a>以下仅为开发过程中的个人经验总结，不具备教学价值，本人主 Java 后端，前端框架使用很不熟练~（2023/08/27 早）</h5></li>
</ul>
<h3 id="快速上手"><a href="#快速上手" class="headerlink" title="快速上手"></a>快速上手</h3><blockquote>
<p>🍖 推荐阅读：<a target="_blank" rel="noopener" href="https://cli.vuejs.org/">Home | Vue CLI (vuejs.org)</a><strong>（2024/01/15 晚）</strong></p>
</blockquote>
<ul>
<li><h5 id="安装脚手架工具（2023-08-05-午）"><a href="#安装脚手架工具（2023-08-05-午）" class="headerlink" title="安装脚手架工具（2023/08/05 午）"></a>安装脚手架工具（2023/08/05 午）</h5></li>
</ul>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs bash">npm install -g @vue/cli<br>OR<br>yarn global add @vue/cli<br></code></pre></td></tr></table></figure>

<ul>
<li><h5 id="使用命令行进行初始化："><a href="#使用命令行进行初始化：" class="headerlink" title="使用命令行进行初始化："></a>使用命令行进行初始化：</h5></li>
</ul>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">vue create antd-demo  <span class="hljs-comment">#项目名</span><br></code></pre></td></tr></table></figure>

<p><img src="http://blog.memory-life.xyz/image-20230826202427695.png" alt="image-20230826202427695"></p>
<p><img src="http://blog.memory-life.xyz/image-20240115221613317.png" alt="image-20240115221613317"></p>
<p><img src="http://blog.memory-life.xyz/image-20230826202435390.png" alt="image-20230826202435390"></p>
<p><img src="http://blog.memory-life.xyz/image-20240115221624382.png" alt="image-20240115221624382"></p>
<ul>
<li><h5 id="按需选择，按我那样的设置就行，引入-TS、Router-等"><a href="#按需选择，按我那样的设置就行，引入-TS、Router-等" class="headerlink" title="按需选择，按我那样的设置就行，引入 TS、Router 等"></a>按需选择，按我那样的设置就行，引入 TS、Router 等</h5></li>
<li><p>注意这里同意保存预设的话，之后构建项目就会按照这次的配置直接构建了，如果要修改项目构建配置，则需执行以下代码：</p>
</li>
</ul>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">npm uninstall -g @vue/cli<br></code></pre></td></tr></table></figure>

<ul>
<li><h5 id="然后重新构建（2023-08-26-晚）"><a href="#然后重新构建（2023-08-26-晚）" class="headerlink" title="然后重新构建（2023/08/26 晚）"></a>然后重新构建（2023/08/26 晚）</h5></li>
</ul>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">npx @vue/cli create antd-demo	<span class="hljs-comment">#在临时目录中执行 @vue/cli 命令，而不依赖于全局路径设置</span><br></code></pre></td></tr></table></figure>

<h3 id="引入-Ant-Design-组件"><a href="#引入-Ant-Design-组件" class="headerlink" title="引入 Ant Design 组件"></a>引入 Ant Design 组件</h3><ul>
<li><h5 id="引入组件："><a href="#引入组件：" class="headerlink" title="引入组件："></a>引入组件：</h5></li>
</ul>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">npm i --save ant-design-vue<br></code></pre></td></tr></table></figure>

<ul>
<li><h5 id="在-main-ts-中如此配置，引入-Ant-Design-组件："><a href="#在-main-ts-中如此配置，引入-Ant-Design-组件：" class="headerlink" title="在 main.ts 中如此配置，引入 Ant Design 组件："></a>在 main.ts 中如此配置，引入 Ant Design 组件：</h5></li>
</ul>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs ts"><span class="hljs-keyword">import</span> &#123; createApp &#125; <span class="hljs-keyword">from</span> <span class="hljs-string">&quot;vue&quot;</span>;<br><span class="hljs-keyword">import</span> <span class="hljs-title class_">App</span> <span class="hljs-keyword">from</span> <span class="hljs-string">&quot;./App.vue&quot;</span>;<br><span class="hljs-keyword">import</span> router <span class="hljs-keyword">from</span> <span class="hljs-string">&quot;./router&quot;</span>;<br><span class="hljs-keyword">import</span> <span class="hljs-title class_">Antd</span> <span class="hljs-keyword">from</span> <span class="hljs-string">&quot;ant-design-vue&quot;</span>;<br><br><span class="hljs-title function_">createApp</span>(<span class="hljs-title class_">App</span>).<span class="hljs-title function_">use</span>(router).<span class="hljs-title function_">use</span>(<span class="hljs-title class_">Antd</span>).<span class="hljs-title function_">mount</span>(<span class="hljs-string">&quot;#app&quot;</span>);<br></code></pre></td></tr></table></figure>

<ul>
<li><h5 id="启动项目：（2023-08-05-午）"><a href="#启动项目：（2023-08-05-午）" class="headerlink" title="启动项目：（2023/08/05 午）"></a>启动项目：（2023/08/05 午）</h5></li>
</ul>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">npm run serve<br></code></pre></td></tr></table></figure>

<h3 id="配置路由"><a href="#配置路由" class="headerlink" title="配置路由"></a>配置路由</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">npm install vue-router@4<br></code></pre></td></tr></table></figure>

<ul>
<li><h5 id="route-ts-中如此初始化："><a href="#route-ts-中如此初始化：" class="headerlink" title="route.ts 中如此初始化："></a>route.ts 中如此初始化：</h5></li>
</ul>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs ts"><span class="hljs-keyword">const</span> <span class="hljs-attr">routes</span>: <span class="hljs-title class_">Array</span>&lt;<span class="hljs-title class_">RouteRecordRaw</span>&gt; = [<br>  &#123;<br>    <span class="hljs-attr">path</span>: <span class="hljs-string">&quot;/&quot;</span>,<br>    <span class="hljs-attr">name</span>: <span class="hljs-string">&quot;index&quot;</span>,<br>    <span class="hljs-attr">component</span>: <span class="hljs-title class_">IndexPage</span>,<br>  &#125;,<br>  &#123;<br>    <span class="hljs-attr">path</span>: <span class="hljs-string">&quot;/about&quot;</span>,<br>    <span class="hljs-attr">name</span>: <span class="hljs-string">&quot;about&quot;</span>,<br>    <span class="hljs-attr">component</span>: <span class="hljs-function">() =&gt;</span><br>      <span class="hljs-keyword">import</span>(<span class="hljs-comment">/* webpackChunkName: &quot;about&quot; */</span> <span class="hljs-string">&quot;../views/AboutView.vue&quot;</span>),<br>  &#125;,<br>];<br></code></pre></td></tr></table></figure>

<h3 id="封装全局-axios"><a href="#封装全局-axios" class="headerlink" title="封装全局 axios"></a>封装全局 axios</h3><p><a target="_blank" rel="noopener" href="http://www.axios-js.com/">axios 中文网|axios API 中文文档 | axios (axios-js.com)</a></p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">npm install axios<br></code></pre></td></tr></table></figure>

<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><code class="hljs ts"><span class="hljs-keyword">import</span> axios <span class="hljs-keyword">from</span> <span class="hljs-string">&quot;axios&quot;</span>;<br><br><span class="hljs-keyword">const</span> instance = axios.<span class="hljs-title function_">create</span>(&#123;<br>  <span class="hljs-attr">baseURL</span>: <span class="hljs-string">&quot;http://localhost:8102/api&quot;</span>,<br>  <span class="hljs-attr">timeout</span>: <span class="hljs-number">10000</span>,<br>  <span class="hljs-attr">headers</span>: &#123;&#125;,<br>&#125;);<br><br><span class="hljs-comment">// 添加响应拦截器</span><br>instance.<span class="hljs-property">interceptors</span>.<span class="hljs-property">response</span>.<span class="hljs-title function_">use</span>(<br>  <span class="hljs-keyword">function</span> (<span class="hljs-params">response</span>) &#123;<br>    <span class="hljs-comment">// 2xx 范围内的状态码都会触发该函数。</span><br>    <span class="hljs-comment">// 对响应数据做点什么</span><br>    <span class="hljs-keyword">const</span> data = response.<span class="hljs-property">data</span>;<br>    <span class="hljs-keyword">if</span> (data.<span class="hljs-property">code</span> === <span class="hljs-number">0</span>) &#123;<br>      <span class="hljs-keyword">return</span> data.<span class="hljs-property">data</span>;<br>    &#125;<br>    <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">error</span>(<span class="hljs-string">&quot;request error&quot;</span>, data);<br>    <span class="hljs-keyword">return</span> response.<span class="hljs-property">data</span>;<br>  &#125;,<br>  <span class="hljs-keyword">function</span> (<span class="hljs-params">error</span>) &#123;<br>    <span class="hljs-comment">// 超出 2xx 范围的状态码都会触发该函数。</span><br>    <span class="hljs-comment">// 对响应错误做点什么</span><br>    <span class="hljs-keyword">return</span> <span class="hljs-title class_">Promise</span>.<span class="hljs-title function_">reject</span>(error);<br>  &#125;<br>);<br><br><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> instance;<br></code></pre></td></tr></table></figure>

<h3 id="路由嵌套"><a href="#路由嵌套" class="headerlink" title="路由嵌套"></a>路由嵌套</h3><ul>
<li><h5 id="app-vue-中如此配置：（2023-08-27-早）"><a href="#app-vue-中如此配置：（2023-08-27-早）" class="headerlink" title="app.vue 中如此配置：（2023/08/27 早）"></a>app.vue 中如此配置：（2023/08/27 早）</h5></li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;template&gt;<br>  &lt;router-view /&gt;<br>&lt;/template&gt;<br></code></pre></td></tr></table></figure>

<ul>
<li>这里解释一下：</li>
</ul>
<figure class="highlight autohotkey"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs autohotkey">在Ant Design Vue中，App.vue是项目的根组件，是所有页面组件的父容器。在这段代码中，`&lt;router-view/&gt;`是一个特殊的组件标签，它用于显示路由器（router）根据当前路由匹配的页面组件。<br><br>`&lt;router-view/&gt;`是Vue Router提供的一个占位符标签，它会根据当前的URL路径匹配到的路由，动态地渲染对应的组件内容。<br><br>具体来说，当用户访问不同的URL路径时，Vue Router会根据定义的路由规则来确定显示哪个组件。然后，这个组件会被动态地渲染到App.vue中的`&lt;router-view/&gt;`标签中。<br></code></pre></td></tr></table></figure>

<ul>
<li><h5 id="比如说当前-URL-中的-path-路径为：-about"><a href="#比如说当前-URL-中的-path-路径为：-about" class="headerlink" title="比如说当前 URL 中的 path 路径为：/about"></a>比如说当前 URL 中的 path 路径为：/about</h5></li>
<li><p>而我们配置的路由中：</p>
</li>
</ul>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs javascript">&#123;<br>  <span class="hljs-attr">path</span>: <span class="hljs-string">&#x27;/about&#x27;</span>,<br>  <span class="hljs-attr">name</span>: <span class="hljs-string">&#x27;about&#x27;</span>,<br>  <span class="hljs-attr">component</span>: <span class="hljs-function">() =&gt;</span> <span class="hljs-keyword">import</span>(<span class="hljs-comment">/* webpackChunkName: &quot;about&quot; */</span> <span class="hljs-string">&#x27;../views/AboutView.vue&#x27;</span>)<br>&#125;<br></code></pre></td></tr></table></figure>

<ul>
<li><h5 id="那么就会展示-about-下的组件内容了"><a href="#那么就会展示-about-下的组件内容了" class="headerlink" title="那么就会展示/about 下的组件内容了"></a>那么就会展示/about 下的组件内容了</h5></li>
<li><p>我在主页面中引入了标签页组件：</p>
</li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;!--标签页--&gt;<br>&lt;a-tabs v-model:activeKey=&quot;activeKey&quot;&gt;<br>      &lt;a-tab-pane key=&quot;文章&quot; tab=&quot;文章&quot;&gt;<br>      &lt;PostList :post-list=&quot;postList&quot;/&gt;<br>      &lt;/a-tab-pane&gt;<br><br>      &lt;a-tab-pane key=&quot;图片&quot; tab=&quot;图片&quot;&gt;<br>        图片<br>      &lt;/a-tab-pane&gt;<br><br>      &lt;a-tab-pane key=&quot;用户&quot; tab=&quot;用户&quot;&gt;<br>        用户<br>      &lt;/a-tab-pane&gt;<br>    &lt;/a-tabs&gt;<br></code></pre></td></tr></table></figure>

<ul>
<li><h5 id="可以看到在-tab-栏下，我引入了-PostList-组件，并传入了-postList-参数"><a href="#可以看到在-tab-栏下，我引入了-PostList-组件，并传入了-postList-参数" class="headerlink" title="可以看到在 tab 栏下，我引入了 PostList 组件，并传入了 postList 参数"></a>可以看到在 tab 栏下，我引入了 PostList 组件，并传入了 postList 参数</h5></li>
<li><h5 id="那么-PostList-组件就会展示在该标签栏下，效果如下：（2023-08-27-早）"><a href="#那么-PostList-组件就会展示在该标签栏下，效果如下：（2023-08-27-早）" class="headerlink" title="那么 PostList 组件就会展示在该标签栏下，效果如下：（2023/08/27 早）"></a>那么 PostList 组件就会展示在该标签栏下，效果如下：（2023/08/27 早）</h5></li>
</ul>
<p><img src="http://blog.memory-life.xyz/image-20230826215450284.png" alt="image-20230826215450284"></p>
<h3 id="子页面嵌套"><a href="#子页面嵌套" class="headerlink" title="子页面嵌套"></a>子页面嵌套</h3><ul>
<li>纠正以下上面说明的页面组件的嵌套方法，正确的嵌套方法应该是这样的：</li>
<li>在 index 页面下引入子组件：</li>
</ul>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs ts">&lt;script lang=<span class="hljs-string">&quot;ts&quot;</span> setup=<span class="hljs-string">&quot;ts&quot;</span>&gt;<br>  <span class="hljs-keyword">import</span> <span class="hljs-title class_">UserListPage</span> <span class="hljs-keyword">from</span> <span class="hljs-string">&quot;@/components/userListPage.vue&quot;</span>;<br>  .......................<br>&lt;/script&gt;<br></code></pre></td></tr></table></figure>

<ul>
<li>子组件编写如下（<strong>注意导出参数 name</strong>）：</li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;template&gt;<br>  &lt;div&gt;嘿嘿嘿&lt;/div&gt;<br>&lt;/template&gt;<br><br>&lt;script&gt;<br>export default &#123;<br>  name: &quot;UserListPage&quot;,<br>&#125;;<br>&lt;/script&gt;<br></code></pre></td></tr></table></figure>

<ul>
<li>直接如此引用子组件（<strong>还可传递参数</strong>，可参考上面 <strong>路由嵌套</strong> 的实现方法）</li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;a-tab-pane key=&quot;1&quot; tab=&quot;用户列表&quot;&gt;<br>              在线用户列表<br>              &lt;UserListPage/&gt;<br>            &lt;/a-tab-pane&gt;<br></code></pre></td></tr></table></figure>

<ul>
<li>那么子页面如何获取传递的参数呢？</li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;a-list<br>          item-layout=&quot;horizontal&quot;<br>          :grid=&quot;&#123; gutter: 16, xs: 1, sm: 2, md: 4, lg: 4, xl: 6, xxl: 6 &#125;&quot;<br>          :data-source=&quot;props.userInfoList&quot;<br>      &gt;<br></code></pre></td></tr></table></figure>

<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><code class="hljs ts">&lt;script setup lang=<span class="hljs-string">&quot;ts&quot;</span>&gt;<br><span class="hljs-keyword">import</span> &#123;withDefaults, defineProps&#125; <span class="hljs-keyword">from</span> <span class="hljs-string">&quot;vue&quot;</span>;<br><br><span class="hljs-keyword">interface</span> <span class="hljs-title class_">Props</span> &#123;<br>  <span class="hljs-attr">userInfoList</span>: <span class="hljs-built_in">any</span>[];<br>&#125;<br><br><span class="hljs-keyword">const</span> props = <span class="hljs-title function_">withDefaults</span>(defineProps&lt;<span class="hljs-title class_">Props</span>&gt;(), &#123;<br>  <span class="hljs-attr">userInfoList</span>: <span class="hljs-function">() =&gt;</span> [],<br>  <span class="hljs-attr">name</span>: <span class="hljs-string">&quot;UserListPage&quot;</span><br>&#125;)<br>&lt;/script&gt;<br></code></pre></td></tr></table></figure>

<ul>
<li><h5 id="完成，页面显示如下，子组件已成功显示在-index-页面中："><a href="#完成，页面显示如下，子组件已成功显示在-index-页面中：" class="headerlink" title="完成，页面显示如下，子组件已成功显示在 index 页面中："></a>完成，页面显示如下，子组件已成功显示在 index 页面中：</h5></li>
</ul>
<p><img src="C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\image-20230909175611698.png" alt="image-20230909175611698"></p>
<h3 id="配置启动端口-1"><a href="#配置启动端口-1" class="headerlink" title="配置启动端口"></a>配置启动端口</h3><ul>
<li><h5 id="在-vue-config-js-下，进行如下配置：（2023-09-09-午）"><a href="#在-vue-config-js-下，进行如下配置：（2023-09-09-午）" class="headerlink" title="在 vue.config.js 下，进行如下配置：（2023/09/09 午）"></a>在 vue.config.js 下，进行如下配置：（2023/09/09 午）</h5></li>
</ul>
<figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs typescript"><span class="hljs-keyword">const</span> &#123; defineConfig &#125; = <span class="hljs-built_in">require</span>(<span class="hljs-string">&quot;@vue/cli-service&quot;</span>);<br><span class="hljs-variable language_">module</span>.<span class="hljs-property">exports</span> = <span class="hljs-title function_">defineConfig</span>(&#123;<br>  <span class="hljs-attr">transpileDependencies</span>: <span class="hljs-literal">true</span>,<br>  <span class="hljs-attr">devServer</span>: &#123;<br>    <span class="hljs-attr">port</span>: <span class="hljs-number">7071</span>,<br>  &#125;,<br>&#125;);<br></code></pre></td></tr></table></figure>

<h3 id="双向绑定"><a href="#双向绑定" class="headerlink" title="双向绑定"></a>双向绑定</h3><ul>
<li>做登录页面时，一个简单的表单和数据双向绑定搞了半天，这里直接给出代码示例了：（2023/09/10 午）</li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;a-form @submit=&quot;handleSubmit&quot;&gt;<br>        &lt;a-form-item label=&quot;用户名&quot; name=&quot;username&quot;<br>                     :rules=&quot;[&#123; required: true, message: &#x27;请输入用户名&#x27; &#125;]&quot;&gt;<br>          &lt;a-input :placeholder=&quot;&#x27;请输入用户名&#x27;&quot; v-model:value=&quot;userAccount&quot;/&gt;<br>        &lt;/a-form-item&gt;<br><br>        &lt;a-form-item label=&quot;密码&quot; name=&quot;userPassword&quot;<br>                     :rules=&quot;[&#123; required: true, message: &#x27;请输入密码&#x27; &#125;]&quot;&gt;<br>          &lt;a-input :type=&quot;&#x27;password&#x27;&quot; :placeholder=&quot;&#x27;请输入密码&#x27;&quot; v-model:value=&quot;userPassword&quot;<br>          /&gt;<br>        &lt;/a-form-item&gt;<br><br>        &lt;a-form-item&gt;<br>          &lt;a-button type=&quot;primary&quot; html-type=&quot;submit&quot;&gt;登录&lt;/a-button&gt;<br>        &lt;/a-form-item&gt;<br>      &lt;/a-form&gt;<br></code></pre></td></tr></table></figure>

<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><code class="hljs ts"><span class="hljs-comment">// 用户名 密码</span><br><span class="hljs-keyword">const</span> userAccount = <span class="hljs-title function_">ref</span>(<span class="hljs-string">&quot;&quot;</span>);<br><span class="hljs-keyword">const</span> userPassword = <span class="hljs-title function_">ref</span>(<span class="hljs-string">&quot;&quot;</span>);<br><br><span class="hljs-comment">// 登录请求</span><br><span class="hljs-keyword">const</span> <span class="hljs-title function_">handleSubmit</span> = (<span class="hljs-params"></span>) =&gt; &#123;<br>  <span class="hljs-title class_">MyAxios</span>.<span class="hljs-title function_">post</span>(<span class="hljs-string">&quot;/user/login&quot;</span>, &#123;<br>    <span class="hljs-attr">userAccount</span>: userAccount.<span class="hljs-property">value</span>,<br>    <span class="hljs-attr">userPassword</span>: userPassword.<span class="hljs-property">value</span>,<br>  &#125;)<br>    .<span class="hljs-title function_">then</span>(<span class="hljs-function">(<span class="hljs-params">values</span>) =&gt;</span> &#123;<br>      <span class="hljs-comment">// 处理表单提交逻辑</span><br>      <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">&quot;表单数据：&quot;</span>, values);<br>    &#125;)<br>    .<span class="hljs-title function_">catch</span>(<span class="hljs-function">(<span class="hljs-params">error</span>) =&gt;</span> &#123;<br>      <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">error</span>(<span class="hljs-string">&quot;表单验证失败：&quot;</span>, error);<br>    &#125;);<br>&#125;;<br></code></pre></td></tr></table></figure>

<h3 id="日常犯傻"><a href="#日常犯傻" class="headerlink" title="日常犯傻"></a>日常犯傻</h3><ul>
<li><h5 id="使用-Vue-的-ref-语法时，容易忘记取-value（2023-09-13-晚）"><a href="#使用-Vue-的-ref-语法时，容易忘记取-value（2023-09-13-晚）" class="headerlink" title="使用 Vue 的 ref() 语法时，容易忘记取.value（2023/09/13 晚）"></a>使用 Vue 的 ref() 语法时，容易忘记取.value（2023/09/13 晚）</h5></li>
</ul>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs ts"><span class="hljs-keyword">const</span> currentUserId = currentUser.<span class="hljs-property">value</span>.<span class="hljs-property">id</span>;<br></code></pre></td></tr></table></figure>

<ul>
<li><h5 id="访问后端服务器路径，容易忘记写-api"><a href="#访问后端服务器路径，容易忘记写-api" class="headerlink" title="访问后端服务器路径，容易忘记写/api"></a>访问后端服务器路径，容易忘记写/api</h5></li>
</ul>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs ts"><span class="hljs-keyword">const</span> socketUrl = <span class="hljs-string">`ws://localhost:8081/api/websocket/<span class="hljs-subst">$&#123;currentUserId&#125;</span>`</span>;<br></code></pre></td></tr></table></figure>

<h3 id="处理-JSON-字符串"><a href="#处理-JSON-字符串" class="headerlink" title="处理 JSON 字符串"></a>处理 JSON 字符串</h3><ul>
<li><h5 id="前台获取服务器转发的消息后，需要解析出接收者，再判断接收者是否为当前用户，是则为该用户展示具体消息（2023-09-14-晚）"><a href="#前台获取服务器转发的消息后，需要解析出接收者，再判断接收者是否为当前用户，是则为该用户展示具体消息（2023-09-14-晚）" class="headerlink" title="前台获取服务器转发的消息后，需要解析出接收者，再判断接收者是否为当前用户，是则为该用户展示具体消息（2023/09/14 晚）"></a>前台获取服务器转发的消息后，需要解析出接收者，再判断接收者是否为当前用户，是则为该用户展示具体消息（2023/09/14 晚）</h5></li>
</ul>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs ts"><span class="hljs-comment">//获得消息事件(获得服务端转发的消息)</span><br>socket.<span class="hljs-property">onmessage</span> = <span class="hljs-keyword">function</span> (<span class="hljs-params">msg</span>) &#123;<br>  <span class="hljs-comment">// 封装返回消息</span><br>  receiveMsg.<span class="hljs-property">value</span> = msg.<span class="hljs-property">data</span>;<br>  <span class="hljs-comment">// 解构</span><br>  <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">&quot;这条消息是发给: &quot;</span> + receiveMsg.<span class="hljs-property">value</span> + <span class="hljs-string">&quot; 的&quot;</span>);<br>  <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">&quot;这条消息是发给: &quot;</span> + receiveMsg.<span class="hljs-property">value</span>.<span class="hljs-property">receiverId</span> + <span class="hljs-string">&quot; 的&quot;</span>);<br>  <span class="hljs-keyword">const</span> content = receiveMsg.<span class="hljs-property">value</span>.<span class="hljs-property">content</span>;<br>  <span class="hljs-comment">// 是否属于我的消息</span><br>  <span class="hljs-keyword">if</span> (receiverId === currentUserId) &#123;<br>    <span class="hljs-title function_">setMessage</span>(<span class="hljs-string">&quot;服务端回应: &quot;</span> + content + <span class="hljs-string">&quot;发给: &quot;</span> + receiverId);<br>  &#125;<br>&#125;;<br></code></pre></td></tr></table></figure>

<ul>
<li>前端返回的 mes 是 JSON 字符串，我看见控制台输出的内容是，以为<strong>是个对象</strong>，结果取到的属性值是 undefined：</li>
</ul>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">&#123;<span class="hljs-string">&quot;senderId&quot;</span>:<span class="hljs-string">&quot;1657284783190523906&quot;</span>,<span class="hljs-string">&quot;receiverId&quot;</span>:<span class="hljs-string">&quot;1657284893320364034&quot;</span>,<span class="hljs-string">&quot;content&quot;</span>:<span class="hljs-string">&quot;阿发&quot;</span>,<span class="hljs-string">&quot;sendTime&quot;</span>:<span class="hljs-string">&quot;2023-09-14T13:29:11.309Z&quot;</span>&#125;<br></code></pre></td></tr></table></figure>

<ul>
<li>调试了半天，检查了下 mes 的类型，才发现是个<strong>JSON 字符串</strong>，奶奶的</li>
</ul>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">console.log(<span class="hljs-string">&quot;type of &quot;</span> + typeof (receiveMsg.value))<br></code></pre></td></tr></table></figure>

<ul>
<li><h5 id="所以要将-msg-JSON-字符串解析为对象后，才可以正常拿到属性值"><a href="#所以要将-msg-JSON-字符串解析为对象后，才可以正常拿到属性值" class="headerlink" title="所以要将 msg JSON 字符串解析为对象后，才可以正常拿到属性值"></a>所以要将 msg JSON 字符串解析为对象后，才可以正常拿到属性值</h5></li>
</ul>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs javascript">receiveMsg.<span class="hljs-property">value</span> = <span class="hljs-title class_">JSON</span>.<span class="hljs-title function_">parse</span>(msg.<span class="hljs-property">data</span>);<br></code></pre></td></tr></table></figure>

<ul>
<li><p>但是连接服务器 socket 时，也会执行这里的代码，而<strong>服务器首次响应连接请求并传回的的参数类型</strong>却<strong>不是 JSON 字符串</strong></p>
</li>
<li><h5 id="解析失败，报以下错误："><a href="#解析失败，报以下错误：" class="headerlink" title="解析失败，报以下错误："></a>解析失败，报以下错误：</h5></li>
</ul>
<p><img src="http://blog.memory-life.xyz/image-20230914214515079.png" alt="image-20230914214515079"></p>
<ul>
<li>最后优化代码，同时处理两种情况：服务器首次连接成功后的响应（<strong>普通字符串</strong>） / 服务器转发的消息（<strong>JSON 字符串</strong>）</li>
</ul>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><code class="hljs ts"><span class="hljs-comment">//获得消息事件(获得服务端转发的消息)</span><br>socket.<span class="hljs-property">onmessage</span> = <span class="hljs-keyword">function</span> (<span class="hljs-params">msg</span>) &#123;<br>  <span class="hljs-comment">// 封装返回消息</span><br>  <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> msg === <span class="hljs-title class_">String</span>) &#123;<br>    receiveMsg.<span class="hljs-property">value</span> = <span class="hljs-title class_">JSON</span>.<span class="hljs-title function_">parse</span>(msg.<span class="hljs-property">data</span>);<br>  &#125;<br>  receiveMsg.<span class="hljs-property">value</span> = msg.<span class="hljs-property">data</span>;<br>  <span class="hljs-comment">// 解构</span><br>  <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">&quot;这条消息是发给: &quot;</span> + receiveMsg.<span class="hljs-property">value</span>.<span class="hljs-property">receiverId</span> + <span class="hljs-string">&quot; 的&quot;</span>);<br>  <span class="hljs-keyword">const</span> content = receiveMsg.<span class="hljs-property">value</span>.<span class="hljs-property">content</span>;<br>  <span class="hljs-comment">// 是否属于我的消息</span><br>  <span class="hljs-keyword">if</span> (receiverId === currentUserId) &#123;<br>    <span class="hljs-title function_">setMessage</span>(<span class="hljs-string">&quot;服务端回应: &quot;</span> + content + <span class="hljs-string">&quot;发给: &quot;</span> + receiverId);<br>  &#125;<br>&#125;;<br></code></pre></td></tr></table></figure>

<ul>
<li><h5 id="各种坑都能踩到，不过好在花点时间排错，都能解决掉-👏👏👏（2023-09-14-晚）"><a href="#各种坑都能踩到，不过好在花点时间排错，都能解决掉-👏👏👏（2023-09-14-晚）" class="headerlink" title="各种坑都能踩到，不过好在花点时间排错，都能解决掉 👏👏👏（2023/09/14 晚）"></a>各种坑都能踩到，不过好在花点时间排错，都能解决掉 👏👏👏（2023/09/14 晚）</h5></li>
</ul>
<h3 id="页面路由跳转（2）"><a href="#页面路由跳转（2）" class="headerlink" title="页面路由跳转（2）"></a>页面路由跳转（2）</h3><ul>
<li><p>在 Vue 中如何实现路由跳转？使用 <strong>umi/router</strong> 组件</p>
</li>
<li><h5 id="Vue-Router-和-组合式-API-Vue-Router-vuejs-org"><a href="#Vue-Router-和-组合式-API-Vue-Router-vuejs-org" class="headerlink" title="Vue Router 和 组合式 API | Vue Router (vuejs.org)"></a><a target="_blank" rel="noopener" href="https://router.vuejs.org/zh/guide/advanced/composition-api.html">Vue Router 和 组合式 API | Vue Router (vuejs.org)</a></h5></li>
<li><h5 id="快速记录一下：（2023-09-16-早）"><a href="#快速记录一下：（2023-09-16-早）" class="headerlink" title="快速记录一下：（2023/09/16 早）"></a>快速记录一下：（2023/09/16 早）</h5></li>
<li><p>我们之前配置过的页面路由是这样的：</p>
</li>
</ul>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs ts">&#123;<br>    <span class="hljs-attr">path</span>: <span class="hljs-string">&#x27;/chat&#x27;</span>,<br>        <span class="hljs-attr">name</span>: <span class="hljs-string">&#x27;chat&#x27;</span>,<br>            <span class="hljs-attr">component</span>: <span class="hljs-function">() =&gt;</span> <span class="hljs-keyword">import</span>(<span class="hljs-comment">/* webpackChunkName: &quot;about&quot; */</span> <span class="hljs-string">&#x27;../pages/chatPage.vue&#x27;</span>)<br>&#125;,<br></code></pre></td></tr></table></figure>

<ul>
<li><h5 id="包含-path（页面路由）、name（页面别名）、component（页面展示组件）"><a href="#包含-path（页面路由）、name（页面别名）、component（页面展示组件）" class="headerlink" title="包含 path（页面路由）、name（页面别名）、component（页面展示组件）"></a>包含 path（页面路由）、name（页面别名）、component（页面展示组件）</h5></li>
<li><p>那么我们可以如此实现<strong>精准的页面跳转</strong>和参数传递：</p>
</li>
</ul>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><code class="hljs ts"><span class="hljs-keyword">import</span> router <span class="hljs-keyword">from</span> <span class="hljs-string">&quot;@/router&quot;</span>;<br><br>router.<span class="hljs-title function_">push</span>(&#123;<br>  <span class="hljs-attr">name</span>: <span class="hljs-string">&quot;chat&quot;</span>,<br>  <span class="hljs-attr">path</span>: <span class="hljs-string">&quot;/chat&quot;</span>,<br>  <span class="hljs-attr">query</span>: &#123;<br>    <span class="hljs-attr">chatUserId</span>: <span class="hljs-number">12345</span>,<br>  &#125;,<br>  <span class="hljs-attr">params</span>: &#123;<br>    <span class="hljs-attr">id</span>: <span class="hljs-string">&quot;12345&quot;</span>,<br>  &#125;,<br>&#125;);<br></code></pre></td></tr></table></figure>

<ul>
<li>也可以简单的<strong>改变当前页面的路由参数</strong>，而不进<strong>行页面跳转</strong>：（<strong>适用于 Tab 页之间切换时，标记 tab 页</strong>）</li>
</ul>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs ts"><span class="hljs-keyword">import</span> router <span class="hljs-keyword">from</span> <span class="hljs-string">&quot;@/router&quot;</span>;<br><br>router.<span class="hljs-title function_">push</span>(&#123;<br>  <span class="hljs-attr">query</span>: &#123;<br>    <span class="hljs-attr">name</span>: <span class="hljs-string">&quot;abab&quot;</span>,<br>  &#125;,<br>&#125;);<br></code></pre></td></tr></table></figure>

<ul>
<li>那么跳转过去的页面该如何获取<strong>当前页面的路由地址</strong>、<strong>携带的参数</strong>等信息呢？<strong>引入 Vue Router 组件</strong>：（2023/09/16 早）</li>
</ul>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs ts"><span class="hljs-keyword">import</span> &#123; useRoute &#125; <span class="hljs-keyword">from</span> <span class="hljs-string">&quot;vue-router&quot;</span>;<br><br><span class="hljs-keyword">const</span> route = <span class="hljs-title function_">useRoute</span>();<br><span class="hljs-title function_">onMounted</span>(<span class="hljs-function">() =&gt;</span> &#123;<br>  <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">&quot;携带参数:&quot;</span>, route.<span class="hljs-property">query</span>);<br>  <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">&quot;路由地址:&quot;</span>, route.<span class="hljs-property">path</span>);<br>  <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">&quot;传递参数:&quot;</span>, route.<span class="hljs-property">params</span>);<br>&#125;);<br></code></pre></td></tr></table></figure>

<h3 id="动态新增-tab-标签页"><a href="#动态新增-tab-标签页" class="headerlink" title="动态新增 tab 标签页"></a>动态新增 tab 标签页</h3><ul>
<li>这是一个很有意思的实现，浅浅记录一下：</li>
</ul>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs ts">&lt;a-tabs v-<span class="hljs-attr">model</span>:activeKey=<span class="hljs-string">&quot;activeKey&quot;</span> tab-position=<span class="hljs-string">&quot;left&quot;</span> <span class="hljs-meta">@change</span>=<span class="hljs-string">&quot;handleTabChange&quot;</span>&gt;<br>     <span class="language-xml"><span class="hljs-tag">&lt;<span class="hljs-name">a-tab-pane</span> <span class="hljs-attr">v-for</span>=<span class="hljs-string">&quot;tab in tabs&quot;</span> <span class="hljs-attr">:key</span>=<span class="hljs-string">&quot;tab.key&quot;</span> <span class="hljs-attr">:tab</span>=<span class="hljs-string">&quot;tab.tab.chatTabName&quot;</span>&gt;</span></span><br><span class="language-xml">       <span class="hljs-comment">&lt;!-- 在这里放置标签页内容 --&gt;</span></span><br><span class="language-xml">       &#123;&#123; tab.content &#125;&#125;</span><br><span class="language-xml">     <span class="hljs-tag">&lt;/<span class="hljs-name">a-tab-pane</span>&gt;</span></span><br>&lt;/a-tabs&gt;<br></code></pre></td></tr></table></figure>

<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><code class="hljs ts"><span class="hljs-comment">// 钩子函数</span><br><span class="hljs-title function_">onMounted</span>(<span class="hljs-function">() =&gt;</span> &#123;<br>  <span class="hljs-title function_">addTab</span>();<br>&#125;);<br><span class="hljs-comment">// 动态添加tab标签页</span><br><span class="hljs-keyword">const</span> <span class="hljs-title function_">addTab</span> = (<span class="hljs-params"></span>) =&gt; &#123;<br>  chatTabName.<span class="hljs-property">value</span> = route.<span class="hljs-property">query</span>;<br>  <span class="hljs-keyword">const</span> newTab = &#123;<br>    <span class="hljs-attr">key</span>: <span class="hljs-title class_">Date</span>.<span class="hljs-title function_">now</span>().<span class="hljs-title function_">toString</span>(), <span class="hljs-comment">// 每个标签页都需要一个唯一的 key</span><br>    <span class="hljs-attr">tab</span>: chatTabName.<span class="hljs-property">value</span>,<br>    <span class="hljs-attr">content</span>: <span class="hljs-string">&quot;新标签页内容&quot;</span>,<br>  &#125;;<br><br>  tabs.<span class="hljs-property">value</span>.<span class="hljs-title function_">push</span>(newTab);<br>  activeKey.<span class="hljs-property">value</span> = newTab.<span class="hljs-property">key</span>; <span class="hljs-comment">// 新增的标签页设为激活状态</span><br>&#125;;<br></code></pre></td></tr></table></figure>

<ul>
<li><h5 id="这样就轻松实现了（MemoryChat-开放过程中的废弃想法-）（2023-09-16-午）"><a href="#这样就轻松实现了（MemoryChat-开放过程中的废弃想法-）（2023-09-16-午）" class="headerlink" title="这样就轻松实现了（MemoryChat 开放过程中的废弃想法 ）（2023/09/16 午）"></a>这样就轻松实现了（MemoryChat 开放过程中的废弃想法 ）（2023/09/16 午）</h5></li>
</ul>
<h3 id="icon-图标的使用"><a href="#icon-图标的使用" class="headerlink" title="icon 图标的使用"></a>icon 图标的使用</h3><ul>
<li><h5 id="看官网，首先下载安装相关依赖：（2023-09-17-晚）"><a href="#看官网，首先下载安装相关依赖：（2023-09-17-晚）" class="headerlink" title="看官网，首先下载安装相关依赖：（2023/09/17 晚）"></a>看官网，首先下载安装相关依赖：（2023/09/17 晚）</h5></li>
</ul>
<figure class="highlight coffeescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs coffeescript"><span class="hljs-built_in">npm</span> install --save @ant-design/icons-vue<br></code></pre></td></tr></table></figure>

<ul>
<li><strong>引入相关 icon 图标 组件</strong>（这步操作，，WebStorm 是不会自动给你引入这个组件的，怪不得我 tab 标签页 的页面图标不显示，一个星期都没解决掉，这编译器害人不浅）</li>
</ul>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs ts"><span class="hljs-keyword">import</span> &#123; <span class="hljs-title class_">StarOutlined</span>, <span class="hljs-title class_">StarFilled</span>, <span class="hljs-title class_">StarTwoTone</span> &#125; <span class="hljs-keyword">from</span> <span class="hljs-string">&quot;@ant-design/icons-vue&quot;</span>;<br></code></pre></td></tr></table></figure>

<ul>
<li><h5 id="直接在页面中用就行了，效果如下："><a href="#直接在页面中用就行了，效果如下：" class="headerlink" title="直接在页面中用就行了，效果如下："></a>直接在页面中用就行了，效果如下：</h5></li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;div&gt;<br>            &lt;StarOutlined /&gt;<br>            &lt;StarFilled /&gt;<br>            &lt;StarTwoTone twoToneColor=&quot;#eb2f96&quot; /&gt;<br>          &lt;/div&gt;<br></code></pre></td></tr></table></figure>

<p><img src="C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\image-20230918190908215.png" alt="image-20230918190908215"></p>
<h3 id="监听选中的-Tab-标签页"><a href="#监听选中的-Tab-标签页" class="headerlink" title="监听选中的 Tab 标签页"></a>监听选中的 Tab 标签页</h3><ul>
<li>我们选中 Tab 标签页后，如果绑定了 activeKey，就会将该 Tab 页的 Key 值，给到 activeKey</li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;a-tab-pane<br>  v-model:activeKey=&quot;activeKey&quot;<br>  v-for=&quot;tab in friendList&quot;<br>  :key=&quot;tab.id&quot;<br>  :tab=&quot;tab.username&quot;<br>  @click=&quot;handleTabChange&quot;<br>&gt;<br>       .........................     <br>    &lt;/a-tab-pane&gt;<br></code></pre></td></tr></table></figure>

<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs ts"><span class="hljs-comment">// tab页 key</span><br><span class="hljs-keyword">const</span> activeKey = <span class="hljs-title function_">ref</span>(currentUserId);<br></code></pre></td></tr></table></figure>

<ul>
<li><h5 id="即，通过选中标签页的动作，就能拿到该-Tab-标签页的-key-值"><a href="#即，通过选中标签页的动作，就能拿到该-Tab-标签页的-key-值" class="headerlink" title="即，通过选中标签页的动作，就能拿到该 Tab 标签页的 key 值"></a>即，通过选中标签页的动作，就能拿到该 Tab 标签页的 key 值</h5></li>
<li><p>那么当页面刷新后，仍然会执行这个代码，初始化 activeKey 的值：</p>
</li>
</ul>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs ts"><span class="hljs-keyword">const</span> activeKey = <span class="hljs-title function_">ref</span>(currentUserId);<br></code></pre></td></tr></table></figure>

<ul>
<li>我们现在要实现：刷新页面后，仍然选中刚才选中的 Tab 标签页，即 activeKey 值需要更新，更新为刚才的 key 值</li>
<li>但是，当页面刷新后 activeKey 的值就丢失了，所以我们要<strong>对 active 进行监听</strong>，随时保存它的值，如下：</li>
</ul>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs ts"><span class="hljs-comment">// 监听 activeKey 的变化，更新存储中的值</span><br><span class="hljs-title function_">watch</span>(activeKey, <span class="hljs-function">(<span class="hljs-params">value</span>) =&gt;</span> &#123;<br>  <span class="hljs-variable language_">localStorage</span>.<span class="hljs-title function_">setItem</span>(<span class="hljs-string">&quot;activeKey&quot;</span>, value);<br>&#125;);<br></code></pre></td></tr></table></figure>

<ul>
<li><p>这里踩了个<strong>坑</strong>，监听的值一定是<strong>activeKey</strong>，而不是<strong>activeKey.value</strong>，即监听的变量是<strong>响应式变量</strong> <strong>（2023/09/20 晚）</strong></p>
</li>
<li><p>那么在页面刷新之后，我们就可以拿到<strong>localStorage 中存储的 key 值</strong>，保持选中刚才的 Tab 页面</p>
</li>
</ul>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs ts"><span class="hljs-comment">// 钩子函数</span><br><span class="hljs-title function_">onMounted</span>(<span class="hljs-function">() =&gt;</span> &#123;<br>........................<br><br>  activeKey.<span class="hljs-property">value</span> = <span class="hljs-variable language_">localStorage</span>.<span class="hljs-title function_">getItem</span>(<span class="hljs-string">&#x27;activeKey&#x27;</span>)<br>.....................<br>&#125;)<br></code></pre></td></tr></table></figure>

<h3 id="点击跳转不同的页面"><a href="#点击跳转不同的页面" class="headerlink" title="点击跳转不同的页面"></a>点击跳转不同的页面</h3><ul>
<li><h5 id="我要讲什么呢，好像还没说清楚，但我举个例子就好理解了"><a href="#我要讲什么呢，好像还没说清楚，但我举个例子就好理解了" class="headerlink" title="我要讲什么呢，好像还没说清楚，但我举个例子就好理解了"></a>我要讲什么呢，好像还没说清楚，但我举个例子就好理解了</h5></li>
<li><p>我最近要实现这样的功能：点击博文，跳转到该博文的详情页</p>
<ul>
<li>这样的需求很常见，掘金、CSDN 等博客网站都是这样，甚至说所有的文档网站都是这样吧</li>
<li>要点就这几个：跳转前拿到该博文 id，跳转页面时携带 id，对应页面解析拿到该 id 从数据库中查询数据</li>
<li>这就是最简单的实现方式了</li>
</ul>
</li>
<li><h5 id="跳转前拿到该博文-id"><a href="#跳转前拿到该博文-id" class="headerlink" title="跳转前拿到该博文 id"></a>跳转前拿到该博文 id</h5></li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;!--博文--&gt;<br>&lt;a-card hoverable @click=&quot;goToRead(item.id)&quot;&gt;<br>     ......................<br>  &lt;/a-card&gt;<br></code></pre></td></tr></table></figure>

<ul>
<li><h5 id="跳转页面时携带-id"><a href="#跳转页面时携带-id" class="headerlink" title="跳转页面时携带 id"></a>跳转页面时携带 id</h5></li>
</ul>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><code class="hljs ts"><span class="hljs-comment">// 跳转博文详情页</span><br><span class="hljs-keyword">const</span> <span class="hljs-title function_">goToRead</span> = (<span class="hljs-params">id: <span class="hljs-built_in">never</span></span>) =&gt; &#123;<br>  <span class="hljs-comment">// router.push(`/blog/read/$&#123;id&#125;`)</span><br>  router.<span class="hljs-title function_">push</span>(&#123;<br>    <span class="hljs-attr">name</span>: <span class="hljs-string">&quot;blogRead&quot;</span>,<br>    <span class="hljs-attr">path</span>: <span class="hljs-string">&quot;/blog/read&quot;</span>,<br>    <span class="hljs-attr">query</span>: &#123;<br>      <span class="hljs-attr">articleId</span>: id,<br>    &#125;,<br>  &#125;);<br>&#125;;<br></code></pre></td></tr></table></figure>

<ul>
<li><h5 id="对应页面解析拿到该-id-从数据库中查询数据"><a href="#对应页面解析拿到该-id-从数据库中查询数据" class="headerlink" title="对应页面解析拿到该 id 从数据库中查询数据"></a>对应页面解析拿到该 id 从数据库中查询数据</h5></li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;template&gt;<br>  &lt;div class=&quot;blog&quot;&gt;<br>    &#123;&#123; articleId &#125;&#125;<br>  &lt;/div&gt;<br>&lt;/template&gt;<br><br>&lt;script lang=&quot;ts&quot; setup=&quot;ts&quot;&gt;<br>import &#123; useRoute &#125; from &quot;vue-router&quot;;<br>import &#123; ref &#125; from &quot;vue&quot;;<br><br>const route = useRoute();<br>const articleId = ref();<br>// 获取id值<br>articleId.value = route.query.articleId;<br>&lt;/script&gt;<br></code></pre></td></tr></table></figure>

<ul>
<li><h5 id="就这样简单地记录下思路吧（2023-09-24-午）"><a href="#就这样简单地记录下思路吧（2023-09-24-午）" class="headerlink" title="就这样简单地记录下思路吧（2023/09/24 午）"></a>就这样简单地记录下思路吧（2023/09/24 午）</h5></li>
</ul>
<h3 id="网页中支持-Markdown-语法写博客"><a href="#网页中支持-Markdown-语法写博客" class="headerlink" title="网页中支持 Markdown 语法写博客"></a>网页中支持 Markdown 语法写博客</h3><ul>
<li><h5 id="要在博客网站中支持-Markdown-语法写博客并展示，你可以使用第三方的-Markdown-解析库来解析-Markdown-文本，并将解析后的内容展示在网页上（2023-09-24-晚）"><a href="#要在博客网站中支持-Markdown-语法写博客并展示，你可以使用第三方的-Markdown-解析库来解析-Markdown-文本，并将解析后的内容展示在网页上（2023-09-24-晚）" class="headerlink" title="要在博客网站中支持 Markdown 语法写博客并展示，你可以使用第三方的 Markdown 解析库来解析 Markdown 文本，并将解析后的内容展示在网页上（2023/09/24 晚）"></a>要在博客网站中支持 Markdown 语法写博客并展示，你可以使用第三方的 Markdown 解析库来解析 Markdown 文本，并将解析后的内容展示在网页上（2023/09/24 晚）</h5></li>
<li><p>首先，你需要引入一个适用于 Vue 的 Markdown 解析库，例如<code>markdown-it</code>。可以通过 NPM 安装该库：</p>
</li>
</ul>
<figure class="highlight livescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs livescript"><span class="hljs-built_in">npm</span> install markdown-<span class="hljs-literal">it</span><br></code></pre></td></tr></table></figure>

<ul>
<li>然后，在你的组件中，你可以导入并实例化<code>markdown-it</code>，将 Markdown 文本作为输入，使用<code>.render()</code>方法将其转换为 HTML 并展示在网页上</li>
</ul>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs ts"><span class="hljs-keyword">import</span> <span class="hljs-title class_">MarkdownIt</span> <span class="hljs-keyword">from</span> <span class="hljs-string">&quot;markdown-it&quot;</span>;<br><br><span class="hljs-comment">// Markdown语法</span><br><span class="hljs-keyword">const</span> parsedContent = <span class="hljs-title function_">ref</span>();<br><span class="hljs-keyword">const</span> md = <span class="hljs-keyword">new</span> <span class="hljs-title class_">MarkdownIt</span>();<br><span class="hljs-comment">// 使用Markdown语法接收文章内容</span><br>parsedContent.<span class="hljs-property">value</span> = md.<span class="hljs-title function_">render</span>(articleInfo.<span class="hljs-property">value</span>.<span class="hljs-property">content</span>);<br></code></pre></td></tr></table></figure>

<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;div<br>  v-html=&quot;parsedContent&quot;<br>  style=&quot;position: absolute; margin-left: 10px; margin-right: 10px; margin-top: 20px;&quot;<br>&gt;<br> &lt;/div&gt;<br></code></pre></td></tr></table></figure>

<ul>
<li><p>在上面的示例代码中，我们导入了<code>markdown-it</code>库</p>
<ul>
<li>然后在<code>mounted</code>钩子中实例化了<code>MarkdownIt</code>对象</li>
<li>并将 Markdown 文本<code>this.articleInfo.content</code>传递给其<code>.render()</code>方法来解析为 HTML 并赋值给<code>parsedContent</code></li>
<li>然后我们使用<code>v-html</code>指令将解析后的内容展示在网页上。</li>
</ul>
</li>
<li><h5 id="这样，无论用户使用-Markdown-语法还是普通的-HTML-编写博客内容，页面都会正确展示"><a href="#这样，无论用户使用-Markdown-语法还是普通的-HTML-编写博客内容，页面都会正确展示" class="headerlink" title="这样，无论用户使用 Markdown 语法还是普通的 HTML 编写博客内容，页面都会正确展示"></a>这样，无论用户使用 Markdown 语法还是普通的 HTML 编写博客内容，页面都会正确展示</h5></li>
<li><p>最终效果：</p>
</li>
</ul>
<p><img src="C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\image-20230924235124466.png" alt="image-20230924235124466"></p>
<h3 id="子组件绑定自己独有的属性"><a href="#子组件绑定自己独有的属性" class="headerlink" title="子组件绑定自己独有的属性"></a>子组件绑定自己独有的属性</h3><ul>
<li><p>鬼知道这个标题是什么意思，我简单介绍下：</p>
<ul>
<li>最近在实现<strong>点击队伍，编辑并发布公告的功能</strong>，要求点击队伍后，只有该队伍对应的窗口会弹窗</li>
<li>这就需要每个队伍中，都封装一个控制弹窗出现的变量</li>
<li>我们当然不能在后端封装这个字段了，所以需要在前端做处理</li>
</ul>
</li>
<li><h5 id="完善昨晚的队伍发布公告，遇到了些许小问题："><a href="#完善昨晚的队伍发布公告，遇到了些许小问题：" class="headerlink" title="完善昨晚的队伍发布公告，遇到了些许小问题："></a>完善昨晚的队伍发布公告，遇到了些许小问题：</h5><ul>
<li>由于编辑公告的弹窗是写在 list 列表中的，即每个 team 都有自己的公告弹窗，所以不应该使用一个变量来控制弹窗的出现/消失：</li>
</ul>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs ts"><span class="hljs-comment">// 弹窗</span><br><span class="hljs-keyword">const</span> visible = ref&lt;<span class="hljs-built_in">boolean</span>&gt;(<span class="hljs-literal">false</span>);<br><span class="hljs-comment">// 展示弹窗</span><br><span class="hljs-keyword">const</span> <span class="hljs-title function_">showModal</span> = (<span class="hljs-params">team: <span class="hljs-built_in">any</span></span>) =&gt; &#123;<br>  visible.<span class="hljs-property">value</span> = <span class="hljs-literal">true</span>;<br>&#125;;<br></code></pre></td></tr></table></figure>

<ul>
<li>而应该为每个 team，都分配独有的控制弹窗出现的变量（<strong>showEditWindow</strong>）：</li>
</ul>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><code class="hljs ts">myAxios<br>  .<span class="hljs-title function_">get</span>(<span class="hljs-string">&quot;/team/created&quot;</span>, &#123;<br>    <span class="hljs-attr">params</span>: &#123;<br>      <span class="hljs-attr">loginUserId</span>: userId,<br>    &#125;,<br>  &#125;)<br>  .<span class="hljs-title function_">then</span>(<span class="hljs-function">(<span class="hljs-params">res</span>) =&gt;</span> &#123;<br>    createdTeamList.<span class="hljs-property">value</span> = res.<span class="hljs-property">data</span>.<span class="hljs-property">records</span>.<span class="hljs-title function_">map</span>(<span class="hljs-function">(<span class="hljs-params">team: <span class="hljs-built_in">any</span></span>) =&gt;</span> &#123;<br>      <span class="hljs-keyword">return</span> &#123;<br>        ...team,<br>        <span class="hljs-attr">showEditWindow</span>: <span class="hljs-literal">false</span>,<br>      &#125;;<br>    &#125;);<br>  &#125;);<br></code></pre></td></tr></table></figure>

<ul>
<li>为每一个 team 绑定：</li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;a-button size=&quot;large&quot; danger @click=&quot;showModal(item)&quot;&gt;发布公告&lt;/a-button&gt;<br>&lt;div style=&quot;position: relative&quot;&gt;<br>                    &lt;a-modal v-model:visible=&quot;item.showEditWindow&quot; title=&quot;队伍公告&quot; @ok=&quot;updateAnnouncement(item)&quot;&gt;<br>                      &lt;p&gt;请编辑队伍公告&lt;/p&gt;<br>                      &lt;a-textarea v-model:value=&quot;announcement&quot; style=&quot;height: 100px&quot;/&gt;<br>                    &lt;/a-modal&gt;<br>                  &lt;/div&gt;<br></code></pre></td></tr></table></figure>

<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs ts"><span class="hljs-comment">// 公告弹窗</span><br><span class="hljs-keyword">const</span> <span class="hljs-title function_">showModal</span> = (<span class="hljs-params">team: <span class="hljs-built_in">any</span></span>) =&gt; &#123;<br>  team.<span class="hljs-property">showEditWindow</span> = <span class="hljs-literal">true</span>;<br>&#125;;<br></code></pre></td></tr></table></figure></li>
<li><p>这个思路是普适的，在获取后台传回的数组信息时，为数组内每一个元素都封装自己的独有的元素</p>
</li>
<li><p>在<strong>实现每篇文章的点赞、收藏</strong>，以及<strong>申请加入队伍</strong>中，都是这样的思路<strong>（2023/09/28 午）</strong></p>
</li>
</ul>
<h3 id="Eslint-优化导致-git-代码推送失败"><a href="#Eslint-优化导致-git-代码推送失败" class="headerlink" title="Eslint 优化导致 git 代码推送失败"></a>Eslint 优化导致 git 代码推送失败</h3><ul>
<li>这是我在今晚<strong>推送 Memory API 接口开放平台时</strong>遇到的报错。详情看下图： <strong>（2023/10/18 晚）</strong></li>
</ul>
<p><img src="http://blog.memory-life.xyz/image-20231018214512698.png" alt="image-20231018214512698"></p>
<ul>
<li>如上图所示，使用 git 推送代码竟然报错了，这是什么原因呢？</li>
<li>我们简单罗列出以上的报错信息：</li>
</ul>
<blockquote>
<p>这些错误和警告是由静态代码分析工具 ESLint 提供的。根据报错信息，您遇到了一些问题：</p>
<ol>
<li><code>File ignored because of a matching ignore pattern. Use &quot;--no-ignore&quot; to override</code>：这是一个警告，意味着某些文件被忽略了，因为它们匹配了 <code>.eslintignore</code> 文件中设定的忽略模式。您可以使用 <code>--no-ignore</code> 参数来覆盖这个忽略，让这些文件被检查。</li>
<li><code>&#39;loading&#39; is assigned a value but never used @typescript-eslint/no-unused-vars</code>：这是一个错误，提示您在 <code>InterfaceInfo/index.tsx</code> 文件中定义了 <code>loading</code> 变量，但是从未使用过。您可以删除没被使用的变量，或者使用变量来解决您需要的逻辑。</li>
<li><code>Missing &quot;key&quot; prop for element in array react/jsx-key</code>：这是两个错误，它们指出在您的组件 <code>InterfaceInfo</code> 的 <code>renderDataSource</code> 方法中，两个元素没有提供 <code>key</code> 属性。React 要求在渲染组件数组时，每个元素都要提供一个唯一的 <code>key</code> 属性，以便在更新列表时进行准确的 diff 操作。您需要为这两个元素添加一个适当的 <code>key</code> 属性。</li>
</ol>
</blockquote>
<ul>
<li><p>所以，这样的报错信息是由<strong>静态代码分析工具 ESLint</strong> 导致的<strong>（2023/10/18 晚）</strong></p>
<ul>
<li>我们使用该工具暴露出编码过程中的代码不规范的问题</li>
<li>但是，在推送代码时，这个工具却仍在校验代码的完整性和规范性，</li>
</ul>
</li>
<li><h5 id="在这些代码报错不影响项目运行的前提下，影响了正常的代码提交流程"><a href="#在这些代码报错不影响项目运行的前提下，影响了正常的代码提交流程" class="headerlink" title="在这些代码报错不影响项目运行的前提下，影响了正常的代码提交流程"></a>在这些代码报错不影响项目运行的前提下，影响了正常的代码提交流程</h5></li>
<li><p>解决方法很简单，只需要在 git commit 命令后添加 –no-version ，<strong>绕过 ESLint 工具的代码校验功能</strong>即可（如下）：</p>
</li>
</ul>
<figure class="highlight nginx"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs nginx"><span class="hljs-attribute">git</span> commit -m <span class="hljs-string">&quot;接口调用页面优化 接口参数信息 接口文档预开发&quot;</span> --<span class="hljs-literal">no</span>-verify<br></code></pre></td></tr></table></figure>

<p><img src="http://blog.memory-life.xyz/image-20231018221051988.png" alt="image-20231018221051988"></p>
<ul>
<li>这里其实还有很多<strong>有关 ESLint 的配置管理</strong>，我就暂时不深究了，日后有机会再展开聊聊</li>
</ul>
<h3 id="安装依赖"><a href="#安装依赖" class="headerlink" title="安装依赖"></a>安装依赖</h3><ul>
<li>导入外部插件时，要选择这个选项，嗖嗖嗖就安装好了（可能这个安装默认是 yarn 的缘故）<strong>（2023/11/11 晚）</strong></li>
<li>但是点第一个或者执行以下命令就得卡住好一会儿，还下载安装失败：</li>
</ul>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">npm install moment<br></code></pre></td></tr></table></figure>

<p><img src="http://blog.memory-life.xyz/image-20231111170920323.png" alt="image-20231111170920323"></p>
<h3 id="快速入门-Vue-指南"><a href="#快速入门-Vue-指南" class="headerlink" title="快速入门 Vue 指南"></a>快速入门 Vue 指南</h3><blockquote>
<p>🍖 推荐阅读：<a target="_blank" rel="noopener" href="https://juejin.cn/post/7298927442488442917">写给后端大忙人看的 vue 入门指南 - 掘金 (juejin.cn)</a></p>
<p>还是非常推荐阅读的，我第一次学 Vue 就是跟着黑马的教程学的，这些操作也都过了一遍的</p>
<p>经常使用<strong>脚手架</strong>（<strong>vite</strong>、<strong>vue/cli</strong> 等）<strong>直接构建 Vue 项目</strong>，很方便很快捷</p>
<p>有时间再实操一遍吧，后端开发人员多了解一些 Vue 还是很有必要的<strong>（2023/11/11 晚）</strong></p>
</blockquote>
<h3 id="栅格化布局"><a href="#栅格化布局" class="headerlink" title="栅格化布局"></a>栅格化布局</h3><ul>
<li>简单学习了解了下：<strong>（2023/12/05 早）</strong></li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;div style=&quot;margin-top: 30px&quot;&gt;<br>    &lt;a-row :gutter=&quot;16&quot;&gt;<br>      &lt;a-col :push=&quot;2&quot; :span=&quot;4&quot;&gt;<br>        &lt;div style=&quot;background-color: #4801&quot;&gt;<br>          dd<br>        &lt;/div&gt;<br>      &lt;/a-col&gt;<br><br>      &lt;a-col :push=&quot;2&quot; :span=&quot;15&quot;&gt;<br>        &lt;div style=&quot;background-color: #4801&quot;&gt;<br>          dd<br>        &lt;/div&gt;<br><br>      &lt;/a-col&gt;<br>    &lt;/a-row&gt;<br>  &lt;/div&gt;<br></code></pre></td></tr></table></figure>

<p><img src="http://blog.memory-life.xyz/image-20231205120654539.png" alt="image-20231205120654539"></p>
<h3 id="引入外部组件页面"><a href="#引入外部组件页面" class="headerlink" title="引入外部组件页面"></a>引入外部组件页面</h3><ul>
<li>编写 <code>ComprehensiveArticle.vue</code> 页面：</li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;template&gt;<br>  &lt;div&gt;综合文章&lt;/div&gt;<br>&lt;/template&gt;<br><br>&lt;script setup lang=&quot;ts&quot;&gt;&lt;/script&gt;<br></code></pre></td></tr></table></figure>

<ul>
<li>在 <code>ArticleList.vue</code> 中导入该页面组件：</li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;div style=&quot;width: 500px&quot;&gt;<br>      &lt;a-tabs v-model:activeKey=&quot;activeKey&quot; tab-position=&quot;left&quot;&gt;<br>        &lt;a-tab-pane key=&quot;1&quot; tab=&quot;Tab 1&quot;&gt;<br>          &lt;CompreArticleList/&gt;<br>        &lt;/a-tab-pane&gt;<br>        &lt;a-tab-pane key=&quot;2&quot; tab=&quot;Tab 2&quot;&gt;Content of Tab 2&lt;/a-tab-pane&gt;<br>        &lt;a-tab-pane key=&quot;3&quot; tab=&quot;Tab 3&quot;&gt;Content of Tab 3&lt;/a-tab-pane&gt;<br>      &lt;/a-tabs&gt;<br>    &lt;/div&gt;<br></code></pre></td></tr></table></figure>

<figure class="highlight tsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs tsx">&lt;script setup lang=<span class="hljs-string">&quot;ts&quot;</span>&gt;<br>  <span class="hljs-keyword">import</span> <span class="hljs-title class_">CompreArticleList</span> <span class="hljs-keyword">from</span> <span class="hljs-string">&quot;@/components/CompreArticleList.vue&quot;</span>;<br>  .......................<br>&lt;/script&gt;<br></code></pre></td></tr></table></figure>

<ul>
<li>导入成功！效果如下：<strong>（2023/12/20 晚）</strong></li>
</ul>
<p><img src="http://blog.memory-life.xyz/image-20231220233126380.png" alt="image-20231220233126380"></p>
<ul>
<li>页面优化完成：（2023/12/21 晚）</li>
</ul>
<p><img src="http://blog.memory-life.xyz/image-20231222000308888.png" alt="image-20231222000308888"></p>
<h3 id="引入外部组件页面并传参"><a href="#引入外部组件页面并传参" class="headerlink" title="引入外部组件页面并传参"></a>引入外部组件页面并传参</h3><ul>
<li>外部页面组件 <code>ArticleList</code> 携带参数，参数名为 <code>compreList</code>，参数值为 <code>articleList</code></li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;a-tabs v-model:activeKey=&quot;activeKey&quot; tab-position=&quot;left&quot;&gt;<br>        &lt;a-tab-pane key=&quot;1&quot; tab=&quot;综合&quot;&gt;<br>          &lt;CompreArticleList :compre-list=&quot;articleList&quot;/&gt;<br>        &lt;/a-tab-pane&gt;<br>        &lt;a-tab-pane key=&quot;2&quot; tab=&quot;后端&quot;&gt;<br>        ............................<br> &lt;/a-tabs&gt;<br></code></pre></td></tr></table></figure>

<ul>
<li>编写内部组件 <code>CompreArticleList</code>，接收参数 <code>compreList</code>，使用 <code>a-list</code>组件展示</li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;a-list<br>  class=&quot;demo-loadmore-list&quot;<br>  item-layout=&quot;horizontal&quot;<br>  :data-source=&quot;props.compreList&quot;<br>  style=&quot;width: 400%&quot;<br>&gt;<br>  ................................<br>&lt;/a-list&gt;<br></code></pre></td></tr></table></figure>

<ul>
<li>在 <code>CompreArticleList</code> 下指明接收参数名<strong>（2023/12/22 早）</strong></li>
</ul>
<figure class="highlight tsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs tsx">&lt;script setup lang=<span class="hljs-string">&quot;ts&quot;</span>&gt;<br><span class="hljs-keyword">import</span> &#123;defineProps, withDefaults&#125; <span class="hljs-keyword">from</span> <span class="hljs-string">&quot;vue/dist/vue&quot;</span>;<br><br>..........................................<br><span class="hljs-keyword">interface</span> <span class="hljs-title class_">Props</span> &#123;<br>  <span class="hljs-attr">compreList</span>: <span class="hljs-built_in">any</span>[];<br>&#125;<br><br><span class="hljs-keyword">const</span> props = <span class="hljs-title function_">withDefaults</span>(defineProps&lt;<span class="hljs-title class_">Props</span>&gt;(), &#123;<br>  <span class="hljs-attr">compreList</span>: <span class="hljs-function">() =&gt;</span> [],<br>&#125;);<br><br>&lt;/script&gt;<br></code></pre></td></tr></table></figure>

<h3 id="自定义-icon-图标"><a href="#自定义-icon-图标" class="headerlink" title="自定义 icon 图标"></a>自定义 icon 图标</h3><ul>
<li>复制 SVG 代码：</li>
</ul>
<p><img src="http://blog.memory-life.xyz/image-20240113231259009.png" alt="image-20240113231259009"></p>
<ul>
<li>引入组件：</li>
</ul>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">npm install --save @ant-design/icons-vue<br></code></pre></td></tr></table></figure>

<figure class="highlight tsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs tsx"><span class="hljs-keyword">import</span> <span class="hljs-title class_">Icon</span> <span class="hljs-keyword">from</span> <span class="hljs-string">&quot;@ant-design/icons-vue&quot;</span>;<br></code></pre></td></tr></table></figure>

<ul>
<li>这里推荐阅读：<a target="_blank" rel="noopener" href="https://2x.antdv.com/components/icon-cn#components-icon-demo-custom">Ant Design Vue (antdv.com)</a></li>
<li>添加组件：<strong>（2024/01/13 晚）</strong></li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;Icon :style=&quot;&#123; color: &#x27;hotpink&#x27; &#125;&quot;&gt;<br>          &lt;template #component&gt;<br>            &lt;svg t=&quot;1705158531565&quot; class=&quot;icon&quot; viewBox=&quot;0 0 1024 1024&quot; version=&quot;1.1&quot; <br>            	....................................<br>            &lt;/svg&gt;<br>          &lt;/template&gt;<br>        &lt;/Icon&gt;<br></code></pre></td></tr></table></figure>

<ul>
<li>完成！效果如下：</li>
</ul>
<p><img src="http://blog.memory-life.xyz/image-20240113231553890.png" alt="image-20240113231553890"></p>
<h3 id="组件-textarea-高度动态变化"><a href="#组件-textarea-高度动态变化" class="headerlink" title="组件 textarea 高度动态变化"></a>组件 textarea 高度动态变化</h3><ul>
<li>后台封装返回高度：</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Data</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">Result</span> &#123;<br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 文本框高度</span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">private</span> <span class="hljs-type">int</span> height;<br><br>    ..................................<br>&#125;<br></code></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">public</span> Result <span class="hljs-title function_">getResultCommon</span><span class="hljs-params">(<span class="hljs-type">double</span> result, <span class="hljs-type">double</span> discount, String resultStr, <span class="hljs-type">int</span> height)</span> &#123;<br>       <span class="hljs-comment">// 根据打着折扣计算最终结果</span><br>       <span class="hljs-type">double</span> <span class="hljs-variable">afterDis</span> <span class="hljs-operator">=</span> result * discount;<br><br>       <span class="hljs-type">Result</span> <span class="hljs-variable">calResult</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Result</span>();<br>       calResult.setBeforeDis(<span class="hljs-number">0.0D</span>);<br>       calResult.setAfterDis(<span class="hljs-number">0.0D</span>);<br>       calResult.setBeforeDis(result);<br>       calResult.setAfterDis(afterDis);<br>       calResult.setProcedure(resultStr);<br>       calResult.setHeight(height);<br><br>       <span class="hljs-keyword">return</span> calResult;<br>   &#125;<br></code></pre></td></tr></table></figure>

<ul>
<li>使用 a-textarea 文本框组件，高度随接收参数值 <code>height</code> 动态变化：<strong>（2024/01/14 晚）</strong></li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;a-form-item label=&quot;计算过程&quot;&gt;<br>                  &lt;a-textarea v-model:value=&quot;result.procedure&quot;<br>                              placeholder=&quot;Basic usage&quot; :rows=&quot;result.height&quot;<br>                              style=&quot;font-size: medium;font-weight: bold&quot;&gt;<br>                  &lt;/a-textarea&gt;<br>                &lt;/a-form-item&gt;<br></code></pre></td></tr></table></figure>

<figure class="highlight tsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs tsx"><span class="hljs-keyword">const</span> result = ref&lt;<span class="hljs-title class_">ResultState</span>&gt;(&#123;<br>  <span class="hljs-attr">beforeDis</span>: <span class="hljs-number">0</span>,<br>  <span class="hljs-attr">afterDis</span>: <span class="hljs-number">0</span>,<br>  <span class="hljs-attr">procedure</span>: <span class="hljs-string">&quot;&quot;</span>,<br>  <span class="hljs-attr">height</span>: <span class="hljs-number">5</span>,<br>&#125;);<br></code></pre></td></tr></table></figure>

<h3 id="CSS-选择器巩固"><a href="#CSS-选择器巩固" class="headerlink" title="CSS 选择器巩固"></a>CSS 选择器巩固</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">// 捕获 id = &quot;leftZhankai&quot;</span><br>       <span class="hljs-type">Element</span> <span class="hljs-variable">leftZhankai</span> <span class="hljs-operator">=</span> doc.getElementById(<span class="hljs-string">&quot;leftZhankai&quot;</span>);<br>       <span class="hljs-type">Elements</span> <span class="hljs-variable">heads</span> <span class="hljs-operator">=</span> leftZhankai.select(<span class="hljs-string">&quot;.sons .cont div:nth-of-type(2)&quot;</span>);<br>       <span class="hljs-keyword">for</span> (Element head : heads) &#123;<br>           <span class="hljs-type">Elements</span> <span class="hljs-variable">title</span> <span class="hljs-operator">=</span> head.select(<span class="hljs-string">&quot;&gt;p:nth-of-type(2)&quot;</span>);<br>           <span class="hljs-comment">// Elements author = head.select(&quot;p:nth-of-type(2)&quot;);</span><br>           <span class="hljs-comment">// System.out.println(title.text() + &quot; &quot; + author.text());</span><br>           System.out.println(<span class="hljs-string">&quot;hhh&quot;</span> + title.text());<br>       &#125;<br></code></pre></td></tr></table></figure>

<p><img src="http://blog.memory-life.xyz/image-20231112200526767.png" alt="image-20231112200526767"></p>
<ul>
<li>熟悉 <strong>CSS 选择器</strong>之后，<strong>解析 HTML 文档</strong>获取<strong>标题、诗人和内容</strong>就很轻松了：</li>
</ul>
<p><img src="http://blog.memory-life.xyz/image-20231112202249521.png" alt="image-20231112202249521"></p>
<ul>
<li>存在多个标签，随机选择五个：<strong>（2024/01/16 晚）</strong></li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">// 随机选择五个标签</span><br>List&lt;Element&gt; selectedItems = galleryItem.subList(<span class="hljs-number">0</span>, <span class="hljs-number">5</span>);<br></code></pre></td></tr></table></figure>

<ul>
<li>获取 <code>img</code> 标签的属性：</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">// 打印选中的标签</span><br><span class="hljs-keyword">for</span> (Element item : selectedItems) &#123;<br>	<span class="hljs-type">Elements</span> <span class="hljs-variable">img</span> <span class="hljs-operator">=</span> item.select(<span class="hljs-string">&quot;&gt; a &gt; img&quot;</span>);<br>	<span class="hljs-type">String</span> <span class="hljs-variable">src</span> <span class="hljs-operator">=</span> <span class="hljs-string">&quot;https:&quot;</span> + img.attr(<span class="hljs-string">&quot;data-src&quot;</span>);<br>	<span class="hljs-type">String</span> <span class="hljs-variable">title</span> <span class="hljs-operator">=</span> img.attr(<span class="hljs-string">&quot;title&quot;</span>);<br><br>	<span class="hljs-type">Picture</span> <span class="hljs-variable">picture</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Picture</span>();<br>	picture.setCategory(category);<br>	picture.setTitle(title);<br>	picture.setUrl(src);<br><br>	pictureList.add(picture);<br>&#125;<br></code></pre></td></tr></table></figure>

<h3 id="MarkDown-编辑器"><a href="#MarkDown-编辑器" class="headerlink" title="MarkDown 编辑器"></a>MarkDown 编辑器</h3><p>官方文档：<a target="_blank" rel="noopener" href="https://github.com/bytedance/bytemd">bytedance/bytemd: ByteMD v1 repository (github.com)</a></p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">npm i @bytemd/vue-next<br></code></pre></td></tr></table></figure>

<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">npm i @bytemd/plugin-highlight @bytemd/plugin-gfm<br></code></pre></td></tr></table></figure>

<p>新建 Markdown 编辑器：</p>
<figure class="highlight tsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br></pre></td><td class="code"><pre><code class="hljs tsx">&lt;template&gt;<br>  <span class="language-xml"><span class="hljs-tag">&lt;<span class="hljs-name">Editor</span> <span class="hljs-attr">:value</span>=<span class="hljs-string">&quot;value&quot;</span> <span class="hljs-attr">:plugins</span>=<span class="hljs-string">&quot;plugins&quot;</span> @<span class="hljs-attr">change</span>=<span class="hljs-string">&quot;handleChange&quot;</span> /&gt;</span></span><br>&lt;/template&gt;<br><br><span class="language-xml"><span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">setup</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">&quot;ts&quot;</span>&gt;</span><span class="language-javascript"></span></span><br><span class="language-javascript"><span class="language-xml"><span class="hljs-keyword">import</span> gfm <span class="hljs-keyword">from</span> <span class="hljs-string">&quot;@bytemd/plugin-gfm&quot;</span>;</span></span><br><span class="language-javascript"><span class="language-xml"><span class="hljs-keyword">import</span> highlight <span class="hljs-keyword">from</span> <span class="hljs-string">&quot;@bytemd/plugin-highlight&quot;</span>;</span></span><br><span class="language-javascript"><span class="language-xml"><span class="hljs-keyword">import</span> &#123; <span class="hljs-title class_">Editor</span> &#125; <span class="hljs-keyword">from</span> <span class="hljs-string">&quot;@bytemd/vue-next&quot;</span>;</span></span><br><span class="language-javascript"><span class="language-xml"><span class="hljs-keyword">import</span> &#123; withDefaults, defineProps, ref &#125; <span class="hljs-keyword">from</span> <span class="hljs-string">&quot;vue&quot;</span>;</span></span><br><span class="language-javascript"><span class="language-xml"></span></span><br><span class="language-javascript"><span class="language-xml"><span class="hljs-comment">/**</span></span></span><br><span class="hljs-comment"><span class="language-javascript"><span class="language-xml"> * 定义组件属性类型</span></span></span><br><span class="hljs-comment"><span class="language-javascript"><span class="language-xml"> */</span></span></span><br><span class="language-javascript"><span class="language-xml">interface <span class="hljs-title class_">Props</span> &#123;</span></span><br><span class="language-javascript"><span class="language-xml">  <span class="hljs-attr">value</span>: string;</span></span><br><span class="language-javascript"><span class="language-xml">  mode?: string;</span></span><br><span class="language-javascript"><span class="language-xml">  <span class="hljs-attr">handleChange</span>: <span class="hljs-function">(<span class="hljs-params">v: string</span>) =&gt;</span> <span class="hljs-keyword">void</span>;</span></span><br><span class="language-javascript"><span class="language-xml">&#125;</span></span><br><span class="language-javascript"><span class="language-xml"></span></span><br><span class="language-javascript"><span class="language-xml"><span class="hljs-keyword">const</span> plugins = [</span></span><br><span class="language-javascript"><span class="language-xml">  <span class="hljs-title function_">gfm</span>(),</span></span><br><span class="language-javascript"><span class="language-xml">  <span class="hljs-title function_">highlight</span>(),</span></span><br><span class="language-javascript"><span class="language-xml">  <span class="hljs-comment">// Add more plugins here</span></span></span><br><span class="language-javascript"><span class="language-xml">];</span></span><br><span class="language-javascript"><span class="language-xml"></span></span><br><span class="language-javascript"><span class="language-xml"><span class="hljs-comment">/**</span></span></span><br><span class="hljs-comment"><span class="language-javascript"><span class="language-xml"> * 给组件指定初始值</span></span></span><br><span class="hljs-comment"><span class="language-javascript"><span class="language-xml"> */</span></span></span><br><span class="language-javascript"><span class="language-xml"><span class="hljs-comment">// const props = withDefaults(defineProps&lt;Props&gt;(), &#123;</span></span></span><br><span class="language-javascript"><span class="language-xml"><span class="hljs-comment">//   value: () =&gt; &quot;&quot;,</span></span></span><br><span class="language-javascript"><span class="language-xml"><span class="hljs-comment">//   mode: () =&gt; &quot;split&quot;,</span></span></span><br><span class="language-javascript"><span class="language-xml"><span class="hljs-comment">//   handleChange: (v: string) =&gt; &#123;</span></span></span><br><span class="language-javascript"><span class="language-xml"><span class="hljs-comment">//     console.log(v);</span></span></span><br><span class="language-javascript"><span class="language-xml"><span class="hljs-comment">//   &#125;,</span></span></span><br><span class="language-javascript"><span class="language-xml"><span class="hljs-comment">// &#125;);</span></span></span><br><span class="language-javascript"><span class="language-xml"></span></span><br><span class="language-javascript"><span class="language-xml"><span class="hljs-keyword">const</span> value = <span class="hljs-title function_">ref</span>(<span class="hljs-string">&quot;&quot;</span>);</span></span><br><span class="language-javascript"><span class="language-xml"></span></span><br><span class="language-javascript"><span class="language-xml"><span class="hljs-keyword">const</span> <span class="hljs-title function_">handleChange</span> = (<span class="hljs-params">v: string</span>) =&gt; &#123;</span></span><br><span class="language-javascript"><span class="language-xml">  value.<span class="hljs-property">value</span> = v;</span></span><br><span class="language-javascript"><span class="language-xml">&#125;;</span></span><br><span class="language-javascript"><span class="language-xml"></span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span></span><br><span class="language-xml"></span><br><span class="language-xml"><span class="hljs-tag">&lt;<span class="hljs-name">style</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span></span><br></code></pre></td></tr></table></figure>

<p>在 main.ts 下，引入样式：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">import <span class="hljs-string">&quot;bytemd/dist/index.css&quot;</span>;<br></code></pre></td></tr></table></figure>

<p><img src="http://blog.memory-life.xyz/image-20240201131855728.png" alt="image-20240201131855728"></p>
<h3 id="代码编辑器"><a href="#代码编辑器" class="headerlink" title="代码编辑器"></a>代码编辑器</h3><h3 id="可视化图表"><a href="#可视化图表" class="headerlink" title="可视化图表"></a>可视化图表</h3><blockquote>
<p>2024 年 8 月 28 日</p>
</blockquote>
<p><a target="_blank" rel="noopener" href="https://echarts.apache.org/handbook/zh/basics/import">在项目中引入 ECharts - 入门篇 - 使用手册 - Apache ECharts</a></p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">npm install echarts --save<br></code></pre></td></tr></table></figure>

<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br></pre></td><td class="code"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">template</span>&gt;</span><br>  <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>&#123;&#123; msg &#125;&#125;<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;main&quot;</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">a-card</span> <span class="hljs-attr">title</span>=<span class="hljs-string">&quot;热门搜索词&quot;</span> <span class="hljs-attr">style</span>=<span class="hljs-string">&quot;margin: 10px 20px&quot;</span>&gt;</span><br>      <span class="hljs-tag">&lt;<span class="hljs-name">div</span></span><br><span class="hljs-tag">        <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;main&quot;</span></span><br><span class="hljs-tag">        <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;main&quot;</span></span><br><span class="hljs-tag">        <span class="hljs-attr">:style</span>=<span class="hljs-string">&quot;&#123; float: &#x27;left&#x27;, width: &#x27;100%&#x27;, height: &#x27;400px&#x27; &#125;&quot;</span></span><br><span class="hljs-tag">      &gt;</span><br>        ？？？图表呢？<br>      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">a-card</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;read-the-docs&quot;</span>&gt;</span>Click on the Vite and Vue logos to learn more<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span><br>  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">template</span>&gt;</span><br><br><span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">setup</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">&quot;ts&quot;</span>&gt;</span><span class="language-javascript"></span><br><span class="language-javascript">  <span class="hljs-keyword">import</span> * <span class="hljs-keyword">as</span> echarts <span class="hljs-keyword">from</span> <span class="hljs-string">&quot;echarts&quot;</span>;</span><br><span class="language-javascript">  <span class="hljs-keyword">import</span> &#123; onMounted &#125; <span class="hljs-keyword">from</span> <span class="hljs-string">&quot;vue&quot;</span>;</span><br><span class="language-javascript"></span><br><span class="language-javascript">  <span class="hljs-title function_">onMounted</span>(<span class="hljs-function">() =&gt;</span> &#123;</span><br><span class="language-javascript">    <span class="hljs-title function_">initEcharts</span>();</span><br><span class="language-javascript">  &#125;);</span><br><span class="language-javascript"></span><br><span class="language-javascript">  <span class="hljs-keyword">const</span> <span class="hljs-title function_">initEcharts</span> = (<span class="hljs-params"></span>) =&gt; &#123;</span><br><span class="language-javascript">    <span class="hljs-keyword">const</span> option = &#123;</span><br><span class="language-javascript">      <span class="hljs-attr">title</span>: [</span><br><span class="language-javascript">        &#123;</span><br><span class="language-javascript">          <span class="hljs-attr">text</span>: <span class="hljs-string">&quot;Tangential Polar Bar Label Position (middle)&quot;</span>,</span><br><span class="language-javascript">        &#125;,</span><br><span class="language-javascript">      ],</span><br><span class="language-javascript">      <span class="hljs-attr">polar</span>: &#123;</span><br><span class="language-javascript">        <span class="hljs-attr">radius</span>: [<span class="hljs-number">30</span>, <span class="hljs-string">&quot;80%&quot;</span>],</span><br><span class="language-javascript">      &#125;,</span><br><span class="language-javascript">      <span class="hljs-attr">angleAxis</span>: &#123;</span><br><span class="language-javascript">        <span class="hljs-attr">max</span>: <span class="hljs-number">4</span>,</span><br><span class="language-javascript">        <span class="hljs-attr">startAngle</span>: <span class="hljs-number">75</span>,</span><br><span class="language-javascript">      &#125;,</span><br><span class="language-javascript">      <span class="hljs-attr">radiusAxis</span>: &#123;</span><br><span class="language-javascript">        <span class="hljs-attr">type</span>: <span class="hljs-string">&quot;category&quot;</span>,</span><br><span class="language-javascript">        <span class="hljs-attr">data</span>: [<span class="hljs-string">&quot;a&quot;</span>, <span class="hljs-string">&quot;b&quot;</span>, <span class="hljs-string">&quot;c&quot;</span>, <span class="hljs-string">&quot;d&quot;</span>],</span><br><span class="language-javascript">      &#125;,</span><br><span class="language-javascript">      <span class="hljs-attr">tooltip</span>: &#123;&#125;,</span><br><span class="language-javascript">      <span class="hljs-attr">series</span>: &#123;</span><br><span class="language-javascript">        <span class="hljs-attr">type</span>: <span class="hljs-string">&quot;bar&quot;</span>,</span><br><span class="language-javascript">        <span class="hljs-attr">data</span>: [<span class="hljs-number">2</span>, <span class="hljs-number">1.2</span>, <span class="hljs-number">2.4</span>, <span class="hljs-number">3.6</span>],</span><br><span class="language-javascript">        <span class="hljs-attr">coordinateSystem</span>: <span class="hljs-string">&quot;polar&quot;</span>,</span><br><span class="language-javascript">        <span class="hljs-attr">label</span>: &#123;</span><br><span class="language-javascript">          <span class="hljs-attr">show</span>: <span class="hljs-literal">true</span>,</span><br><span class="language-javascript">          <span class="hljs-attr">position</span>: <span class="hljs-string">&quot;middle&quot;</span>,</span><br><span class="language-javascript">          <span class="hljs-attr">formatter</span>: <span class="hljs-string">&quot;&#123;b&#125;: &#123;c&#125;&quot;</span>,</span><br><span class="language-javascript">        &#125;,</span><br><span class="language-javascript">      &#125;,</span><br><span class="language-javascript">    &#125;;</span><br><span class="language-javascript"></span><br><span class="language-javascript">    <span class="hljs-keyword">const</span> myChart = echarts.<span class="hljs-title function_">init</span>(<span class="hljs-variable language_">document</span>.<span class="hljs-title function_">getElementById</span>(<span class="hljs-string">&quot;main&quot;</span>)); <span class="hljs-comment">// 图标初始化</span></span><br><span class="language-javascript">    myChart.<span class="hljs-title function_">setOption</span>(option); <span class="hljs-comment">// 渲染页面</span></span><br><span class="language-javascript">  &#125;;</span><br><span class="language-javascript"></span><br><span class="language-javascript">  <span class="hljs-keyword">function</span> defineProps&lt;T&gt;() &#123;&#125;</span><br><span class="language-javascript"></span><br><span class="language-javascript">  defineProps&lt;&#123; <span class="hljs-attr">msg</span>: string &#125;&gt;();</span><br><span class="language-javascript"></span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span><br></code></pre></td></tr></table></figure>

<p>妈的，一晚上啥也没干成。。图表就是不显示。前端真的麻烦。</p>
<blockquote>
<p>2024 年 8 月 29 日</p>
</blockquote>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;template&gt;<br>  &lt;div&gt;<br>    &lt;h1&gt;&#123;&#123; msg &#125;&#125;&lt;/h1&gt;<br>    &lt;div<br>      class=&quot;main&quot;<br>      id=&quot;main&quot;<br>      style=&quot;float: left ;width: 100%; height: 400px &quot;<br>    &gt;&lt;/div&gt;<br>    &lt;p class=&quot;read-the-docs&quot;&gt;Click on the Vite and Vue logos to learn more&lt;/p&gt;<br>  &lt;/div&gt;<br>&lt;/template&gt;<br></code></pre></td></tr></table></figure>

<p>原来必须指定标签宽高才能正常显示统计表的，我之前怎么没遇到过这样的问题呢。</p>
<figure class="highlight tsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><code class="hljs tsx"><span class="hljs-keyword">import</span> * <span class="hljs-keyword">as</span> echarts <span class="hljs-keyword">from</span> <span class="hljs-string">&quot;echarts&quot;</span>;<br><br><span class="hljs-keyword">const</span> <span class="hljs-title function_">initEcharts</span> = (<span class="hljs-params"></span>) =&gt; &#123;<br>  <span class="hljs-keyword">const</span> option = &#123;<br>    <span class="hljs-attr">title</span>: [<br>      &#123;<br>        <span class="hljs-attr">text</span>: <span class="hljs-string">&quot;Tangential Polar Bar Label Position (middle)&quot;</span>,<br>      &#125;,<br>    ],<br>    <span class="hljs-attr">polar</span>: &#123;<br>      <span class="hljs-attr">radius</span>: [<span class="hljs-number">30</span>, <span class="hljs-string">&quot;80%&quot;</span>],<br>    &#125;,<br>    <span class="hljs-attr">angleAxis</span>: &#123;<br>      <span class="hljs-attr">max</span>: <span class="hljs-number">4</span>,<br>      <span class="hljs-attr">startAngle</span>: <span class="hljs-number">75</span>,<br>    &#125;,<br>    <span class="hljs-attr">radiusAxis</span>: &#123;<br>      <span class="hljs-attr">type</span>: <span class="hljs-string">&quot;category&quot;</span>,<br>      <span class="hljs-attr">data</span>: [<span class="hljs-string">&quot;a&quot;</span>, <span class="hljs-string">&quot;b&quot;</span>, <span class="hljs-string">&quot;c&quot;</span>, <span class="hljs-string">&quot;d&quot;</span>],<br>    &#125;,<br>    <span class="hljs-attr">tooltip</span>: &#123;&#125;,<br>    <span class="hljs-attr">series</span>: &#123;<br>      <span class="hljs-attr">type</span>: <span class="hljs-string">&quot;bar&quot;</span>,<br>      <span class="hljs-attr">data</span>: [<span class="hljs-number">2</span>, <span class="hljs-number">1.2</span>, <span class="hljs-number">2.4</span>, <span class="hljs-number">3.6</span>],<br>      <span class="hljs-attr">coordinateSystem</span>: <span class="hljs-string">&quot;polar&quot;</span>,<br>      <span class="hljs-attr">label</span>: &#123;<br>        <span class="hljs-attr">show</span>: <span class="hljs-literal">true</span>,<br>        <span class="hljs-attr">position</span>: <span class="hljs-string">&quot;middle&quot;</span>,<br>        <span class="hljs-attr">formatter</span>: <span class="hljs-string">&quot;&#123;b&#125;: &#123;c&#125;&quot;</span>,<br>      &#125;,<br>    &#125;,<br>  &#125;;<br><br>  <span class="hljs-keyword">const</span> myChart = echarts.<span class="hljs-title function_">init</span>(<span class="hljs-variable language_">document</span>.<span class="hljs-title function_">getElementById</span>(<span class="hljs-string">&quot;main&quot;</span>)); <span class="hljs-comment">// 图标初始化</span><br>  myChart.<span class="hljs-title function_">setOption</span>(option); <span class="hljs-comment">// 渲染页面</span><br>&#125;;<br></code></pre></td></tr></table></figure>

<p><img src="C:/Users/Lenovo/AppData/Roaming/Typora/typora-user-images/image-20240829172043879.png" alt="image-20240829172043879"></p>
<h3 id="Layout-布局"><a href="#Layout-布局" class="headerlink" title="Layout 布局"></a>Layout 布局</h3><blockquote>
<p>2024 年 9 月 1 日</p>
</blockquote>
<p>这个组件可太好用了，直接就能拿来做后台管理页面：</p>
<p><a target="_blank" rel="noopener" href="https://2x.antdv.com/components/layout-cn">Ant Design Vue (antdv.com)</a></p>
<p><img src="http://blog.memory-life.xyz/image-20240901192102785.png" alt="image-20240901192102785"></p>
<p>不过源码里都有 BUG ，这里简单修改下就可以：</p>
<figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs css"><span class="hljs-selector-class">.logo</span> &#123;<br>  <span class="hljs-attribute">height</span>: <span class="hljs-number">32px</span>;<br>  <span class="hljs-attribute">margin</span>: <span class="hljs-number">16px</span>;<br>  <span class="hljs-attribute">background</span>: <span class="hljs-built_in">rgba</span>(<span class="hljs-number">255</span>, <span class="hljs-number">255</span>, <span class="hljs-number">255</span>, <span class="hljs-number">0.3</span>);<br>  <span class="hljs-attribute">font-size</span>: large;<br>  <span class="hljs-attribute">color</span>: lavender;<br>  <span class="hljs-attribute">font-weight</span>: bold;<br>&#125;<br></code></pre></td></tr></table></figure>

<p>我根据功能模块很快就把基本的框架搭建完成：</p>
<p><img src="http://blog.memory-life.xyz/image-20240901192220474.png" alt="image-20240901192220474"></p>
<p>昨天还在研究这个页头和侧边导航菜单怎么搭配才好看，页面做了个大概不太好看，但睡觉之前总算研究出点击导航栏的交互逻辑：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;a-menu<br>        theme=&quot;dark&quot;<br>        v-model:selectedKeys=&quot;selectedKeys&quot;<br>        v-model:openKeys=&quot;openKeys&quot;<br>        mode=&quot;inline&quot;<br>        @click=&quot;handleClick&quot;<br>      &gt;<br>  &lt;a-sub-menu key=&quot;institution&quot; @titleClick=&quot;titleClick&quot;&gt;<br>          &lt;template #title&gt;<br>            &lt;span&gt;<br>              &lt;user-outlined /&gt;<br>              &lt;span&gt;组织机构&lt;/span&gt;<br>            &lt;/span&gt;<br>          &lt;/template&gt;<br>          &lt;a-menu-item key=&quot;institution_1&quot;&gt;机构管理&lt;/a-menu-item&gt;<br>          &lt;a-menu-item key=&quot;institution_2&quot;&gt;角色管理&lt;/a-menu-item&gt;<br>          &lt;a-menu-item key=&quot;institution_3&quot;&gt;用户管理&lt;/a-menu-item&gt;<br>          &lt;a-menu-item key=&quot;institution_4&quot;&gt;岗位管理&lt;/a-menu-item&gt;<br>        &lt;/a-sub-menu&gt;<br></code></pre></td></tr></table></figure>

<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-comment">//点击菜单</span><br><span class="hljs-keyword">const</span> <span class="hljs-title function_">handleClick</span> = (<span class="hljs-params">e: Event</span>) =&gt; &#123;<br>  message.<span class="hljs-title function_">info</span>(<span class="hljs-string">&quot;handleClick&quot;</span> + <span class="hljs-title class_">JSON</span>.<span class="hljs-title function_">stringify</span>(e));<br>&#125;;<br><br><span class="hljs-comment">// 点击展开菜单</span><br><span class="hljs-keyword">const</span> <span class="hljs-title function_">titleClick</span> = (<span class="hljs-params">e: Event</span>) =&gt; &#123;<br>  message.<span class="hljs-title function_">info</span>(<span class="hljs-string">&quot;titleClick&quot;</span> + <span class="hljs-title class_">JSON</span>.<span class="hljs-title function_">stringify</span>(e));<br>&#125;;<br></code></pre></td></tr></table></figure>

<p>这样就可以很轻松地实现点击菜单 / 点击展开菜单后的交互逻辑：</p>
<p><img src="http://blog.memory-life.xyz/image-20240901192703020.png" alt="image-20240901192703020"></p>
<p>我之前做过的 Vue.js 项目中，用路由和基本布局组件（BasicLayoutView）实现了主体内容根据路由发生变化，就是 content 这块内容：</p>
<p><img src="http://blog.memory-life.xyz/image-20240901192913681.png" alt="image-20240901192913681"></p>
<p>怎么实现呢？App.vue 文件下这样写：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;template&gt;<br>  &lt;template v-if=&quot;route.path.startsWith(&#x27;/user&#x27;)&quot;&gt;<br>    &lt;router-view /&gt;<br>  &lt;/template&gt;<br>  &lt;template v-else&gt;<br>    &lt;div id=&quot;app&quot;&gt;<br>      &lt;BasicLayout /&gt;<br>    &lt;/div&gt;<br>  &lt;/template&gt;<br>&lt;/template&gt;<br></code></pre></td></tr></table></figure>

<p>也就是除了登录页面，其余所有页面均展示 BasicLayout 组件内容，即登录页面是这样的：</p>
<p><img src="http://blog.memory-life.xyz/image-20240901193620589.png" alt="image-20240901193620589"></p>
<p>在 BasicLayout 的 content 下这样写，当然就实现了根据当前路由，页面局部展示组件了：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;!--正文--&gt;<br>&lt;a-layout-content style=&quot;margin: 0 16px&quot;&gt;<br>        &lt;a-breadcrumb style=&quot;margin: 16px 0&quot;&gt;<br>          &lt;a-breadcrumb-item&gt;User&lt;/a-breadcrumb-item&gt;<br>          &lt;a-breadcrumb-item&gt;Bill&lt;/a-breadcrumb-item&gt;<br>        &lt;/a-breadcrumb&gt;<br><br>        &lt;div<br>          :style=&quot;&#123; padding: &#x27;24px&#x27;, background: &#x27;#fff&#x27;, minHeight: &#x27;360px&#x27; &#125;&quot;<br>        &gt;<br>          &lt;router-view /&gt;<br>        &lt;/div&gt;<br>      &lt;/a-layout-content&gt;<br></code></pre></td></tr></table></figure>

<p>只要路由配置好以后，路由对应的组件显示就不会有问题。</p>
<p>值得一提的是，点击菜单后接收到的 event ，我尝试转为 json 对象，打印出来后是 json 字符串：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs js">message.<span class="hljs-title function_">info</span>(<span class="hljs-string">&quot;handleClick&quot;</span> + <span class="hljs-title class_">JSON</span>.<span class="hljs-title function_">stringify</span>(e));<br></code></pre></td></tr></table></figure>

<p>然后转换为 JS 对象，就可以直接取到点击的菜单 key 值了，如果把 key 值设置为跳转路由，就可以根据路由跳转到指定页面了：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs javascript"><span class="hljs-title class_">JSON</span>.<span class="hljs-title function_">parse</span>(event);<br></code></pre></td></tr></table></figure>

<p>我还写了段测试代码反复比对，原来一个是 JS 对象，一个是 json 字符串，这能一样吗，还得用 JSON.parse(jsonString) 转 JS 对象：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-comment">// 点击菜单</span><br><span class="hljs-keyword">const</span> <span class="hljs-title function_">handleClick</span> = (<span class="hljs-params">e: Event</span>) =&gt; &#123;<br>  message.<span class="hljs-title function_">info</span>(<span class="hljs-string">&quot;handleClick&quot;</span> + <span class="hljs-title class_">JSON</span>.<span class="hljs-title function_">stringify</span>(e));<br>  <span class="hljs-keyword">const</span> event = <span class="hljs-title class_">JSON</span>.<span class="hljs-title function_">stringify</span>(e);<br>  <span class="hljs-keyword">const</span> eventData = &#123;<br>    <span class="hljs-attr">key</span>: <span class="hljs-string">&quot;one_2&quot;</span>,<br>    <span class="hljs-attr">eventKey</span>: <span class="hljs-string">&quot;menu_item_1322_$$_one_2&quot;</span>,<br>    <span class="hljs-attr">keyPath</span>: [<span class="hljs-string">&quot;one&quot;</span>, <span class="hljs-string">&quot;one_2&quot;</span>],<br>    <span class="hljs-attr">eventKeyPath</span>: [<span class="hljs-string">&quot;sub_menu_367_$$_one&quot;</span>, <span class="hljs-string">&quot;menu_item_1322_$$_one_2&quot;</span>],<br>    <span class="hljs-attr">domEvent</span>: &#123; <span class="hljs-attr">isTrusted</span>: <span class="hljs-literal">true</span>, <span class="hljs-attr">_vts</span>: <span class="hljs-number">1725183565175</span> &#125;,<br>    <span class="hljs-attr">item</span>: &#123; <span class="hljs-attr">disabled</span>: <span class="hljs-literal">false</span>, <span class="hljs-attr">danger</span>: <span class="hljs-literal">false</span> &#125;,<br>  &#125;;<br>  <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(event === eventData);<br>  <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-title class_">JSON</span>.<span class="hljs-title function_">parse</span>(event));<br>  <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(eventData);<br>  <span class="hljs-keyword">const</span> key = eventData.<span class="hljs-property">key</span>;<br>  <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(key); <span class="hljs-comment">// 输出: one_2</span><br>&#125;;<br></code></pre></td></tr></table></figure>

<p><img src="http://blog.memory-life.xyz/image-20241002111421869.png" alt="image-20241002111421869"></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs javascript">&lt;script setup lang=<span class="hljs-string">&quot;ts&quot;</span>&gt;<br><br><span class="hljs-keyword">function</span> defineProps&lt;T&gt;(): <span class="hljs-keyword">void</span> &#123;<br>  <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">&quot;&quot;</span>);<br>&#125;<br><br>defineProps&lt;&#123; <span class="hljs-attr">msg</span>: string &#125;&gt;();<br>&lt;/script&gt;<br></code></pre></td></tr></table></figure>

<h3 id="包管理器混合"><a href="#包管理器混合" class="headerlink" title="包管理器混合"></a>包管理器混合</h3><blockquote>
<p>2024 年 9 月 2 日</p>
</blockquote>
<p><img src="http://blog.memory-life.xyz/image-20240902150048738.png" alt="image-20240902150048738"></p>
<h2 id="Layui"><a href="#Layui" class="headerlink" title="Layui"></a>Layui</h2><blockquote>
<p>2024 年 8 月 21 日</p>
</blockquote>
<p><a target="_blank" rel="noopener" href="https://gitee.com/layui/layui">layui: 一套遵循原生态开发模式的 Web UI 组件库，采用自身轻量级模块化规范，极易上手，可以更简单快速地构建网页界面。 (gitee.com)</a></p>
<p><img src="https://i-blog.csdnimg.cn/blog_migrate/bb4a3bebe434b24dfcf1ba78fb36c6c4.png" alt="在这里插入图片描述"></p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/m0_73647713/article/details/131638228?ops_request_misc=%7B%22request_id%22:%22172422530616800226569275%22,%22scm%22:%2220140713.130102334..%22%7D&request_id=172422530616800226569275&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_click~default-2-131638228-null-null.142%5Ev100%5Epc_search_result_base4&utm_term=layui&spm=1018.2226.3001.4187">layui 介绍及入门基础（看我这篇就会了！！！）-CSDN 博客</a></p>
<p>看了两篇文章，基本了解了 laiui，Bootstrap，esasyui 是怎么一回事了，再拉取个开源项目玩玩：<a target="_blank" rel="noopener" href="https://gitee.com/zwens/springboot-manager">springboot-manager: 基于 SpringBoot + Mybatis Plus + SaToken + Thymeleaf + Layui 的后台管理系统 (gitee.com)</a></p>
<p><img src="http://blog.memory-life.xyz/image-20240821164755835.png" alt="image-20240821164755835"></p>
<p>进入官网在线体验地址看了下，这个开源项目我好像用过，好熟悉的页面：</p>
<p><img src="http://blog.memory-life.xyz/image-20240821164956475.png" alt="image-20240821164956475"></p>
<p>有时间就可以研究这个项目了，SpringBoot + Mybatis Plus + SaToken + <em>thymeleaf</em> + Layui 的技术栈，对我而言还是有一定的吸引力。</p>
<p>接下来进入实操环节，我尝试使用 layui 搭建几个好看的页面：</p>
<p>🥩 官网：<a target="_blank" rel="noopener" href="https://gitee.com/layui/layui">layui: 一套遵循原生态开发模式的 Web UI 组件库，采用自身轻量级模块化规范，极易上手，可以更简单快速地构建网页界面。 (gitee.com)</a></p>
<p>下载安装了 layui 源码包，按照官网文档提供的使用步骤成，成功在本地新搭建的 Spring Boot 前后端不分离项目应用了样式。</p>
<p>下载资源包，放在 resource 目录下：</p>
<p><img src="http://blog.memory-life.xyz/image-20240821164217391.png" alt="image-20240821164217391"></p>
<p>在 static 目录下新增 index.html 文件，组件什么的直接官网里找就行了，复制粘贴过来即可：<a target="_blank" rel="noopener" href="https://layui.dev/docs/2/">开始使用 - Layui 文档</a></p>
<p>一定要保证正确引入 .css 和 .js 文件，这样引入：</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span><br>  <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">&quot;utf-8&quot;</span> /&gt;</span><br>  <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;viewport&quot;</span> <span class="hljs-attr">content</span>=<span class="hljs-string">&quot;width=device-width, initial-scale=1&quot;</span> /&gt;</span><br>  <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Demo<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span><br>  <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">href</span>=<span class="hljs-string">&quot;./layui/css/layui.css&quot;</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">&quot;stylesheet&quot;</span> /&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span><br></code></pre></td></tr></table></figure>

<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">&quot;./layui/layui.js&quot;</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span><br></code></pre></td></tr></table></figure>

<p>导入了常见的组件，看看效果。</p>
<p><img src="http://blog.memory-life.xyz/image-20240821163446821.png" alt="image-20240821163446821"></p>
<p><strong>作为一个资深的后端开发人员</strong>，我还是不习惯使用 layui 来开发 Web 项目，无论是全新的组件库还是 Ajax 请求发送流程，都需要学习。</p>
<p>一个简单的登陆页面，使用 layui 封装的 JQurey，向后台服务器发送请求：</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;layui-form-item&quot;</span>&gt;</span><br>  <span class="hljs-tag">&lt;<span class="hljs-name">button</span></span><br><span class="hljs-tag">    <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;layui-btn layui-btn layui-btn-normal layui-btn-fluid&quot;</span></span><br><span class="hljs-tag">    <span class="hljs-attr">lay-submit</span>=<span class="hljs-string">&quot;&quot;</span></span><br><span class="hljs-tag">    <span class="hljs-attr">lay-filter</span>=<span class="hljs-string">&quot;login&quot;</span></span><br><span class="hljs-tag">  &gt;</span><br>    登 入<br>  <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span><br></code></pre></td></tr></table></figure>

<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br></pre></td><td class="code"><pre><code class="hljs js">&lt;script&gt;<br>    <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">&quot;test&quot;</span>);<br>    layui.<span class="hljs-title function_">use</span>(<span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) &#123;<br>        <span class="hljs-keyword">var</span> form = layui.<span class="hljs-property">form</span>,<br>            layer = layui.<span class="hljs-property">layer</span>,<br>            $ = layui.<span class="hljs-property">jquery</span>;<br><br>        <span class="hljs-comment">// 粒子线条背景</span><br>        $(<span class="hljs-variable language_">document</span>).<span class="hljs-title function_">ready</span>(<span class="hljs-keyword">function</span>(<span class="hljs-params"></span>)&#123;<br>            $(<span class="hljs-string">&#x27;.layui-container&#x27;</span>).<span class="hljs-title function_">particleground</span>(&#123;<br>                <span class="hljs-attr">dotColor</span>:<span class="hljs-string">&#x27;#7ec7fd&#x27;</span>,<br>                <span class="hljs-attr">lineColor</span>:<span class="hljs-string">&#x27;#7ec7fd&#x27;</span><br>            &#125;);<br>        &#125;);<br><br>        <span class="hljs-comment">// 进行登录操作</span><br>        form.<span class="hljs-title function_">on</span>(<span class="hljs-string">&#x27;submit(login)&#x27;</span>, <span class="hljs-keyword">function</span> (<span class="hljs-params">data</span>) &#123;<br>            data = data.<span class="hljs-property">field</span>;<br>            <span class="hljs-keyword">if</span> (data.<span class="hljs-property">captcha</span> == <span class="hljs-string">&#x27;&#x27;</span>) &#123;<br>                layer.<span class="hljs-title function_">msg</span>(<span class="hljs-string">&#x27;请输入验证码&#x27;</span>);<br>                <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;<br>            &#125;<br>            <span class="hljs-keyword">if</span> (data.<span class="hljs-property">username</span> == <span class="hljs-string">&#x27;&#x27;</span>) &#123;<br>                layer.<span class="hljs-title function_">msg</span>(<span class="hljs-string">&#x27;用户名不能为空&#x27;</span>);<br>                <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;<br>            &#125;<br>            <span class="hljs-keyword">if</span> (data.<span class="hljs-property">password</span> == <span class="hljs-string">&#x27;&#x27;</span>) &#123;<br>                layer.<span class="hljs-title function_">msg</span>(<span class="hljs-string">&#x27;密码不能为空&#x27;</span>);<br>                <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;<br>            &#125;<br><br>            $.<span class="hljs-title function_">ajax</span>(&#123;<br>                <span class="hljs-attr">type</span>: <span class="hljs-string">&#x27;POST&#x27;</span>,<br>                <span class="hljs-attr">url</span>: ctx + <span class="hljs-string">&#x27;sys/user/login&#x27;</span>,<br>                <span class="hljs-attr">dataType</span>: <span class="hljs-string">&quot;JSON&quot;</span>,<br>                <span class="hljs-attr">data</span>: <span class="hljs-title class_">JSON</span>.<span class="hljs-title function_">stringify</span>(data),<br>                <span class="hljs-attr">contentType</span>: <span class="hljs-string">&quot;application/json&quot;</span>,<br>                <span class="hljs-attr">success</span>: <span class="hljs-keyword">function</span> (<span class="hljs-params">res</span>) &#123;<br>                    <span class="hljs-keyword">if</span> (res.<span class="hljs-property">code</span> == <span class="hljs-number">0</span>) &#123;<br>                        layer.<span class="hljs-title function_">msg</span>(<span class="hljs-string">&#x27;登录成功&#x27;</span>, &#123;<span class="hljs-attr">time</span>: <span class="hljs-number">1000</span>&#125;, <span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) &#123;<br>                            <span class="hljs-variable language_">window</span>.<span class="hljs-property">location</span> = ctx + <span class="hljs-string">&#x27;index/home&#x27;</span>;<br>                        &#125;);<br>                    &#125; <span class="hljs-keyword">else</span> &#123;<br>                        layer.<span class="hljs-title function_">msg</span>(res.<span class="hljs-property">msg</span>);<br>                        $(<span class="hljs-string">&quot;#img&quot;</span>).<span class="hljs-title function_">click</span>();<br>                    &#125;<br>                &#125;<br>            &#125;)<br><br>            <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;<br>        &#125;);<br>    &#125;);<br>&lt;/script&gt;<br></code></pre></td></tr></table></figure>

<p>这就是今天学习 layui 的全部心得，将来一有时间我就会在这里写一些新的体会，总觉得前端代码看多了以后，有种释怀的感觉。</p>
<h2 id="thymeleaf"><a href="#thymeleaf" class="headerlink" title="thymeleaf"></a>thymeleaf</h2><blockquote>
<p>2024 年 8 月 20 日</p>
</blockquote>
<p>今晚完善了自己的 Spring Boot 初始框架：<a target="_blank" rel="noopener" href="https://gitee.com/deng-2022/memory-springboot-init">memory-springboot-init: Spring Boot 初始框架 (gitee.com)</a></p>
<p>以后会慢慢学习和完善。</p>
<p>我想要做一个练习：<a target="_blank" rel="noopener" href="https://blog.csdn.net/qq_52010229/article/details/139416060">前后端不分离与前后端分离的 Java Web 开发对比介绍_java 前后端不分离-CSDN 博客</a></p>
<p>快速地构建一个 Spring Boot 项目，确保导入以下依赖：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br>			<span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.springframework.boot<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>			<span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-boot-starter-web<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>		<span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br>		<span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br>			<span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.projectlombok<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>			<span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>lombok<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>			<span class="hljs-tag">&lt;<span class="hljs-name">optional</span>&gt;</span>true<span class="hljs-tag">&lt;/<span class="hljs-name">optional</span>&gt;</span><br>		<span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br>		<span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br>			<span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.springframework.boot<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>			<span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-boot-starter-test<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>			<span class="hljs-tag">&lt;<span class="hljs-name">scope</span>&gt;</span>test<span class="hljs-tag">&lt;/<span class="hljs-name">scope</span>&gt;</span><br>		<span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br>		<span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br>			<span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.springframework.boot<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>			<span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-boot-starter-thymeleaf<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br>		<span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br></code></pre></td></tr></table></figure>

<p>做好相关配置 appication.xml：</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs yaml"><span class="hljs-attr">spring:</span><br>  <span class="hljs-attr">application:</span><br>    <span class="hljs-attr">name:</span> <span class="hljs-string">spring-demo</span><br>  <span class="hljs-attr">server:</span><br>    <span class="hljs-attr">port:</span> <span class="hljs-number">8080</span><br>  <span class="hljs-attr">thymeleaf:</span><br>    <span class="hljs-attr">cache:</span> <span class="hljs-literal">false</span><br></code></pre></td></tr></table></figure>

<p>新增 Controller 层，处理 Web 请求：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Controller</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">HelloController</span> &#123;<br>    <span class="hljs-meta">@GetMapping(&quot;/hello&quot;)</span><br>    <span class="hljs-keyword">public</span> String <span class="hljs-title function_">sayHello</span><span class="hljs-params">(Model model)</span> &#123;<br>        model.addAttribute(<span class="hljs-string">&quot;message&quot;</span>, <span class="hljs-string">&quot;Hello, World!&quot;</span>);<br>        <span class="hljs-keyword">return</span> <span class="hljs-string">&quot;hello&quot;</span>;<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<p>新增 hello.html：</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><code class="hljs html"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-keyword">html</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">&quot;en&quot;</span>&gt;</span><br>  <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">&quot;UTF-8&quot;</span> /&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Title<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span><br>  <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span><br>  <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">th:text</span>=<span class="hljs-string">&quot;$&#123;message&#125;&quot;</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span><br>  <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span><br></code></pre></td></tr></table></figure>

<p>最终项目结构：</p>
<p><img src="http://blog.memory-life.xyz/image-20240820214137674.png" alt="image-20240820214137674"></p>
<p>启动项目，访问：<a target="_blank" rel="noopener" href="http://localhost:8080/hello">Title</a>，得到以下结果：</p>
<p><img src="http://blog.memory-life.xyz/image-20240820214210911.png" alt="image-20240820214210911"></p>
<blockquote>
<p>2024 年 8 月 21 日</p>
</blockquote>
<p>跟之前学习 layui 的心得是一样的，我希望能更多地接触到新的开源项目，学习那些平常时间里基本没有用到的技术栈。</p>
<p>我总算明白到这样的事实：前后端分离和不分离的开发模式其实相差不大，主要还是纠结前端用什么框架搭建页面比较合适。</p>
<p>像 layui，Bootstrap，easyui 这些，都可以理解为一种 <strong>UI 渲染框架</strong>，我觉得下面这段内容将三者之间的关系缕得很清晰：</p>
<figure class="highlight mipsasm"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><code class="hljs mipsasm"><span class="hljs-number">2</span>.<span class="hljs-number">1</span> layui和<span class="hljs-keyword">bootstrap对比（这两个都属于UI渲染框架）</span><br><span class="hljs-keyword"></span>      <span class="hljs-number">1</span>.layui是国人开发的一套框架，<span class="hljs-number">2016</span>年出来的，现在已更新到<span class="hljs-number">2</span>.X版本了。比较新，轻量级，样式简单好看（目前官网已下架，开源了）<br>      <span class="hljs-number">2</span>.<span class="hljs-keyword">bootstrap </span>相对来说是比较成熟的一个框架，现在已经更新到<span class="hljs-number">4</span>.X版本。是一个很成熟的框架，这个大部分人一般都用过<br><br>        <span class="hljs-number">1</span>）适用范围不一样<br>        <span class="hljs-number">1</span>.layui 其实更偏向与后端开发人员使用，在服务端页面上有非常好的效果。<br>        <span class="hljs-number">2</span>.适合做后台框架<br>        <span class="hljs-number">3</span>.layui是提供给后端开发人员最好的ui框架，基于DOM驱动，在实现前端交互上比较麻烦，页面的增删改查都需要查询DOM元素。所以在不需要交互的时候，用layui还是不错的（说这句话的人，只能说明你对layui不了解）<br>        <span class="hljs-number">4</span>.<span class="hljs-keyword">bootstrap </span>在前端响应式方面做得很好，PC端和移动端表现都不错。<br>        <span class="hljs-number">5</span>.适合做网站<br>        <span class="hljs-number">6</span>.如果是类似官网，且需要同时满足PC端和移动端效果，<span class="hljs-keyword">bootstrap </span>表现很好，但是如果是要交互的网站，比如商城之类，layui显然更好，前后端分离<br>        <span class="hljs-number">2</span>）大小不一样<br>         <span class="hljs-number">1</span>.layui 轻量级<br>         <span class="hljs-number">2</span>.<span class="hljs-keyword">bootsrap </span>因为成熟，所以使用方便，但是同时也是因为成熟，就显得有些冗余<br></code></pre></td></tr></table></figure>

<figure class="highlight apache"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs apache"><span class="hljs-attribute">2</span>.<span class="hljs-number">2</span> layui和easyui对比<br><br>     <span class="hljs-attribute">1</span>.easyui 是非开源的，有需要解决的问题的话，就只能等官方更新了<br>     <span class="hljs-attribute">2</span>.layui是开源的，社区比较活跃，解决问题还是比较快的<br>     <span class="hljs-attribute">3</span>.easyui诞生的早些，所以功能相对完善一些，很多功能都能是比较健全的<br>     <span class="hljs-attribute">4</span>.layui就相对来说少一些了，不过，功能都是像官网说的，精雕细琢<br>     <span class="hljs-attribute">5</span>.layui更符合现在的审美<br></code></pre></td></tr></table></figure>

<p>那到底什么是 thymeleaf 呢？这东西用来干嘛的。其实只要将 thymeleaf 和 vue 比较下，就能很轻松地了解了：</p>
<p><a target="_blank" rel="noopener" href="https://zhidao.baidu.com/question/1506780638165699179.html">vue 和 thymeleaf 区别_百度知道 (baidu.com)</a></p>
<ol>
<li>vue 主要用于构建用户界面和单页面应用，更加侧重于前端开发和视图层的处理，支持响应式编程、声明式渲染和组件化开发等，通过 js 实现前后端数据交互和页面渲染。</li>
<li>thymeleaf 是一个用于 Web 和独立环境的服务器端 Java 模板引擎，能够直接生成 HTML 页面，可以与 Spring 等后端框架无缝集成，主要通过 Java 代码和模板结合实现服务端页面渲染，天生用来实践前后端不分离开发模式。</li>
</ol>
<h2 id="React"><a href="#React" class="headerlink" title="React"></a>React</h2><blockquote>
<p>2025 年 5 月 14 日</p>
</blockquote>
<p><strong>1. 为什么是 <code>text</code> 和 <code>setText</code>？</strong></p>
<p>这是 React 官方推荐的命名约定，本质是 <strong>数组解构赋值</strong> 的语法：</p>
<p>jsx</p>
<p>复制</p>
<figure class="highlight pf"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs pf"><span class="hljs-keyword">const</span> [<span class="hljs-keyword">state</span>, <span class="hljs-built_in">set</span>State] = useState(initialValue);<br>//          │      │<br>//          │      └── 更新函数（约定以 `<span class="hljs-built_in">set</span>` 开头）<br>//          └─── 状态变量<br></code></pre></td></tr></table></figure>

<ul>
<li><p><strong><code>useState</code> 返回值</strong>：返回一个包含两个元素的数组 <code>[state, setState]</code></p>
</li>
<li><p>解构重命名</p>
<p>：你可以自由命名这两个变量，但约定俗成：</p>
<p>jsx</p>
<p>复制</p>
<figure class="highlight axapta"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs axapta"><span class="hljs-keyword">const</span> [userName, setUserName] = useState(<span class="hljs-string">&quot;&quot;</span>); <span class="hljs-comment">// 例如表单字段</span><br><span class="hljs-keyword">const</span> [<span class="hljs-keyword">count</span>, setCount] = useState(<span class="hljs-number">0</span>);        <span class="hljs-comment">// 例如计数器</span><br></code></pre></td></tr></table></figure></li>
</ul>
<hr>
<p><strong>2. 背后的运行原理</strong></p>
<p>（1）状态初始化</p>
<p>jsx</p>
<p>复制</p>
<figure class="highlight pf"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs pf"><span class="hljs-keyword">const</span> [text, <span class="hljs-built_in">set</span>Text] = useState<span class="hljs-variable">&lt;string&gt;</span>(<span class="hljs-string">&quot;&quot;</span>);<br></code></pre></td></tr></table></figure>

<ul>
<li>React 在组件首次渲染时：<ul>
<li>分配一个<strong>独立的状态存储空间</strong>给当前组件实例</li>
<li>将初始值 <code>&quot;&quot;</code> 存入 <code>text</code>，并生成专用的 <code>setText</code> 函数</li>
</ul>
</li>
</ul>
<p>（2）状态更新流程</p>
<p>jsx</p>
<p>复制</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">McEditor</span> <span class="hljs-attr">onChange</span>=<span class="hljs-string">&#123;setText&#125;</span> /&gt;</span><br></code></pre></td></tr></table></figure>

<ol>
<li><p> <strong>用户输入</strong> → 编辑器触发 <code>onChange</code> 事件 → 调用 <code>setText(&quot;新内容&quot;)</code></p>
</li>
<li><p>React 内部</p>
<p> ：</p>
<ul>
<li>将新值 <code>&quot;新内容&quot;</code> 存入组件状态存储</li>
<li><strong>标记该组件需要重新渲染</strong>（Re-render）</li>
</ul>
</li>
<li><p>重新渲染时</p>
<p> ：</p>
<ul>
<li>再次调用 <code>useState</code>，但此时会返回<strong>更新后的值</strong>（不再是初始值）</li>
<li>所有使用 <code>text</code> 的组件（如 <code>&lt;MDViewer&gt;</code>）会接收到新值</li>
</ul>
</li>
</ol>
<p>（3）关键特性</p>
<ul>
<li><strong>闭包机制</strong>：<code>setText</code> 函数始终绑定到当前组件实例，即使多次渲染也不会丢失</li>
<li><strong>异步批量更新</strong>：连续调用 <code>setText</code> 可能被合并为一次渲染（性能优化）</li>
<li><strong>不可变更新</strong>：必须通过 <code>setText</code> 修改状态，直接修改 <code>text</code> 无效</li>
</ul>
<hr>
<p><strong>3. 为什么必须配对使用？</strong></p>
<ul>
<li><p><code>useState</code> 的设计</p>
<p>：React 故意将状态和更新函数</p>
<p>捆绑返回</p>
<p>，确保：</p>
<ul>
<li>更新函数总是能正确找到对应的状态</li>
<li>避免开发者手动管理状态依赖关系</li>
</ul>
</li>
<li><p>对比 Vue 的 <code>ref</code></p>
<p>：</p>
<p>js</p>
<p>复制</p>
<figure class="highlight arduino"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs arduino"><span class="hljs-comment">// Vue 3 的写法（单个对象包含值和更新逻辑）</span><br><span class="hljs-type">const</span> text = <span class="hljs-built_in">ref</span>(<span class="hljs-string">&quot;&quot;</span>);<br>text.value = <span class="hljs-string">&quot;新值&quot;</span>; <span class="hljs-comment">// 直接修改</span><br></code></pre></td></tr></table></figure>

<p>React 选择分离</p>
<figure class="highlight applescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs applescript"><span class="hljs-built_in">text</span><br></code></pre></td></tr></table></figure>

<p>和</p>
<figure class="highlight ebnf"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs ebnf"><span class="hljs-attribute">setText</span><br></code></pre></td></tr></table></figure>

<p>是为了：</p>
<ul>
<li>更明确的<strong>不可变数据流</strong>（必须通过函数更新）</li>
<li>便于在复杂场景中追踪状态变化</li>
</ul>
</li>
</ul>
<hr>
<p><strong>4. 你可以自由命名吗？</strong></p>
<p><strong>可以！但强烈建议遵循约定</strong>：</p>
<p>jsx</p>
<p>复制</p>
<figure class="highlight axapta"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs axapta"><span class="hljs-keyword">const</span> [<span class="hljs-built_in">str</span>, updateStr] = useState(<span class="hljs-string">&quot;&quot;</span>); <span class="hljs-comment">// 合法但非主流</span><br><span class="hljs-keyword">const</span> [data, setData] = useState(<span class="hljs-string">&quot;&quot;</span>);  <span class="hljs-comment">// 更常见的命名</span><br></code></pre></td></tr></table></figure>

<ul>
<li><strong>行业惯例</strong>：<code>setXxx</code> 命名让其他开发者一眼看出这是状态更新函数</li>
<li><strong>Lint 工具</strong>：ESLint 的 React 规则会警告不符合约定的命名</li>
</ul>
<hr>
<p><strong>5. 完整流程示例</strong></p>
<p>jsx</p>
<p>复制</p>
<figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><code class="hljs typescript"><span class="hljs-keyword">const</span> <span class="hljs-title function_">MyEditor</span> = (<span class="hljs-params"></span>) =&gt; &#123;<br>  <span class="hljs-comment">// 1. 初始化状态（组件首次渲染时执行）</span><br>  <span class="hljs-keyword">const</span> [text, setText] = useState&lt;<span class="hljs-built_in">string</span>&gt;(<span class="hljs-string">&quot;&quot;</span>);<br><br>  <span class="hljs-comment">// 2. 用户输入时的处理</span><br>  <span class="hljs-keyword">const</span> <span class="hljs-title function_">handleChange</span> = (<span class="hljs-params">newText: <span class="hljs-built_in">string</span></span>) =&gt; &#123;<br>    <span class="hljs-title function_">setText</span>(newText); <span class="hljs-comment">// 触发重新渲染</span><br>  &#125;;<br><br>  <span class="hljs-keyword">return</span> (<br>    <span class="language-xml"><span class="hljs-tag">&lt;&gt;</span></span><br><span class="language-xml">      &#123;/* 3. 编辑器绑定状态和更新函数 */&#125;</span><br><span class="language-xml">      <span class="hljs-tag">&lt;<span class="hljs-name">McEditor</span> <span class="hljs-attr">value</span>=<span class="hljs-string">&#123;text&#125;</span> <span class="hljs-attr">onChange</span>=<span class="hljs-string">&#123;handleChange&#125;</span> /&gt;</span></span><br><span class="language-xml"></span><br><span class="language-xml">      &#123;/* 4. 预览器自动同步最新状态 */&#125;</span><br><span class="language-xml">      <span class="hljs-tag">&lt;<span class="hljs-name">MDViewer</span> <span class="hljs-attr">value</span>=<span class="hljs-string">&#123;text&#125;</span> /&gt;</span></span><br><span class="language-xml">    <span class="hljs-tag">&lt;/&gt;</span></span><br>  );<br>&#125;;<br></code></pre></td></tr></table></figure>

<hr>
<p><strong>总结回答你的疑问</strong></p>
<ol>
<li><strong><code>text</code>/<code>setText</code> 是约定而非语法</strong>：你可以用其他名字，但 <code>setXxx</code> 是行业标准</li>
<li><strong>配对原理</strong>：<code>useState</code> 返回的数组解构后，第二个元素永远是更新函数</li>
<li><strong>底层机制</strong>：React 通过闭包和渲染周期管理，确保 <code>setText</code> 总能正确更新对应的 <code>text</code> 状态</li>
</ol>
<p>这种设计是 React <strong>函数式编程</strong>思想的体现，强调显式状态更新而非隐式修改。</p>
<h1 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h1>
                
              </div>
            
            <hr/>
            <div>
              <!-- 文章页面 - 底部标签 -->
<div class="post-metas my-3">
  
  <div class="post-meta mr-3 d-flex align-items-center">
    <i class="iconfont icon-category"></i>
    <!-- 归档页 - 文章列表 -->


<span class="category-chains">
  
  
    
      <span class="category-chain">
        
  <a href="/blog/categories/%E4%BB%A3%E7%A0%81%E9%94%8B%E8%8A%92/" class="category-chain-item">代码锋芒</a>
  
  

      </span>
    
  
</span>

  </div>
   
  <div class="post-meta">
    <i class="iconfont icon-tags"></i>
    
    <a href="/blog/tags/%E7%BB%8F%E9%AA%8C/">#经验</a>
    
    <a href="/blog/tags/%E9%A1%B9%E7%9B%AE/">#项目</a>
    
    <a href="/blog/tags/Vue/">#Vue</a>
    
    <a href="/blog/tags/Ant-Design-Pro/">#Ant Design Pro</a>
    
    <a href="/blog/tags/React/">#React</a>
    
  </div>
  
</div>


              <!-- 文章页面 - 底部标签下方 -->

  
  <div class="license-box my-3">
    <div class="license-title">
      <div>浴火重生：从挫败到成功，前端框架的疑难杂症解决之道</div>
      <div>https://test.atomgit.net/blog/2023/07/21/浴火重生：从挫败到成功，前端框架的疑难杂症解决之道/</div>
    </div>
    <div class="license-meta">
      
        <div class="license-meta-item">
          <div>作者</div>
          <div>Memory</div>
        </div>
      
      
        <div class="license-meta-item license-meta-date">
          <div>发布于</div>
          <div>2023年7月21日</div>
        </div>
      
      
        <div class="license-meta-item license-meta-date">
          <div>更新于</div>
          <div>2025年5月14日</div>
        </div>
      
      
        <div class="license-meta-item">
          <div>许可协议</div>
          <div>
            
              
              
                <a target="_blank" href="https://creativecommons.org/licenses/by/4.0/">
                  <span class="hint--top hint--rounded" aria-label="BY - 署名">
                    <i class="iconfont icon-by"></i>
                  </span>
                </a>
              
            
          </div>
        </div>
      
    </div>
    <div class="license-icon iconfont"></div>
  </div>



              
                <div class="post-prevnext my-3">
                  <article class="post-prev col-6">
                    
                    
                      <a href="/blog/2023/07/30/%E4%B8%80%E6%96%87%E6%90%9E%E5%AE%9A%E7%BD%91%E7%AB%99%E4%B8%8A%E7%BA%BF%EF%BC%9A%E4%BB%8E%E9%9B%B6%E5%88%B0%E4%B8%80%E7%9A%84%E5%AE%9E%E6%88%98%E6%8C%87%E5%8D%97/" title="一文搞定网站上线：从零到一的实战指南">
                        <i class="iconfont icon-arrowleft"></i>
                        <span class="hidden-mobile">一文搞定网站上线：从零到一的实战指南</span>
                        <span class="visible-mobile">上一篇</span>
                      </a>
                    
                  </article>
                  <article class="post-next col-6">
                    
                    
                      <a href="/blog/2023/07/17/%E6%8E%A2%E7%B4%A2%E7%AE%97%E6%B3%95%E5%AD%A6%E4%B9%A0%E4%B9%8B%E6%97%85%EF%BC%9A%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%AB%E4%B8%8E%E8%A7%A3%E9%A2%98%E6%80%9D%E8%B7%AF/" title="探索算法学习之旅：经验分享与解题思路">
                        <span class="hidden-mobile">探索算法学习之旅：经验分享与解题思路</span>
                        <span class="visible-mobile">下一篇</span>
                        <i class="iconfont icon-arrowright"></i>
                      </a>
                    
                  </article>
                </div>
              
            </div>

            <!-- 文章页 - 评论上方 -->

  
  
    <article id="comments">
      
  <div id="valine"></div>
  <script type="text/javascript">
    Fluid.utils.loadComments('#valine', function() {
      Fluid.utils.createScript('https://cdn.jsdelivr.net/gh/HCLonely/Valine@latest/dist/Valine.min.js', function() {
        var options = Object.assign(
          {"appId":"T1hUHH9Ks1ggG9DBE3HgUPpV-gzGzoHsz","appKey":"XFkgzzvzNo3J3uNCbBiSOFKc","path":"window.location.pathname","placeholder":"填取QQ号和邮箱后评论，支持读取头像及消息提醒，留下点什么叭... ᶘ ᵒᴥᵒᶅ","avatar":"Gravatar","meta":["nick","mail","link"],"requiredFields":[],"pageSize":10,"lang":"zh-CN","highlight":true,"recordIP":false,"serverURLs":"https://t1huhh9k.lc-cn-n1-shared.com","emojiCDN":null,"emojiMaps":null,"enableQQ":true,"master":"8c9b6d6637904da62d74d019cc6982de","friends":"0188229a9cfc284176ea9135cb9514cc","visitor":true},
          {
            el: "#valine",
            path: window.location.pathname,
            app_id: "",
            app_key: "",
            placeholder: "填取QQ号和邮箱后评论，支持读取头像及消息提醒，留下点什么叭... ᶘ ᵒᴥᵒᶅ",
            avatar: "Gravatar",
            meta: ["nick","mail","link"],
            pageSize: "10",
            lang: "zh-CN",
            highlight: true,
            recordIP: false,
            serverURLs: "https://t1huhh9k.lc-cn-n1-shared.com",

            // 设置Bilibili表情包地址
            emojiCDN: '//i0.hdslb.com/bfs/emote/', 
            // 表情title和图片映射
            emojiMaps: {
                "tv_白眼": "48f75163437445665a9be80bb316e4cb252c5415.gif@48w_48h.webp",
                "tv_doge": "302d6c88c63ed162c81a49cafe7ed2709e6fb955.gif@48w_48h.webp",
                "tv_坏笑": "5d2572efd09aab5dde9e2a198bb3f9ac1e2a982e.gif@48w_48h.webp",
                "tv_难过": "9c6b41008a67755410f712334c64313df5f91b3f.gif@48w_48h.webp",
                "tv_生气": "1902a5a2df5b5c931d88c12f0feb264b1e109d0d.gif@48w_48h.webp",
                "tv_委屈": "af5a5853edb43a8178a8cb5df707fa5e88143699.gif@48w_48h.webp",
                "tv_斜眼笑": "c66568b471192ca1f62f6ed4384dc1b283ab7508.gif@48w_48h.webp",
                "tv_呆": "d3fa91e4db9215eb1e20ab9da44f1214aa4bda7b.gif@48w_48h.webp",
                "tv_发怒": "3959eb81b952e4fa8d269d98f9e3639172d84073.gif@48w_48h.webp",
                "tv_呕吐": "db58e9442aae26694af18cc1683607cca3a16763.gif@48w_48h.webp",
                "tv_思考": "b63f9146bfd985af014f8d6d4bdb498805be48f9.gif@48w_48h.webp",
                "tv_微笑": "b98656855d782f61cb8edc7f7fca6563ecafff7e.gif@48w_48h.webp",
                "tv_疑问": "fce1b1a0f3b0e39a2dc16a18508dba7b91e929f4.gif@48w_48h.webp",
                "tv_大哭": "cba61f05f3039b02a7ffc0dfcd9d7995df9fdd74.gif@48w_48h.webp",
                "tv_鼓掌": "be106e6b265883a9f28fbe10f7b765701e2618d4.gif@48w_48h.webp",
                "tv_抠鼻": "696d9f93e722144dc2a78aeffc569418fdf3d565.gif@48w_48h.webp",
                "tv_亲亲": "3534ea44ab74bd20352b88c245a06c4b4c46d271.gif@48w_48h.webp",
                "tv_调皮": "fcd967395fd14e4dd5829fa7e8a967ce23205e52.gif@48w_48h.webp",
                "tv_笑哭": "1c2fd1e8c9dde12812f86e5d4cbddd8993d98082.gif@48w_48h.webp",
                "tv_晕": "030040ec5c9ddc9e3d067658c4139e7314ab42f8.gif@48w_48h.webp",
                "tv_点赞": "30ecff401245fb56bcc1cf588d1809ac1ab1607c.gif@48w_48h.webp",
                "tv_害羞": "411a3e459e8580f5bfd9f639a408247c4b509935.gif@48w_48h.webp",
                "tv_睡着": "3c8b5e293261287a6203597e29b3de07df4d18c6.gif@48w_48h.webp",
                "tv_色": "a0c6d99ab0ab63b8648f5283ff72cec04b604828.gif@48w_48h.webp",
                "tv_吐血": "e17e4539e169d14a3389ff147afea760cebe5de5.gif@48w_48h.webp",
                "tv_无奈": "eb4cb5f07cfd177c7e6a7914316717e56d9cc1d0.gif@48w_48h.webp",
                "tv_再见": "344f61609ecce2008520dc8a977b6169215748a9.gif@48w_48h.webp",
                "tv_流汗": "390bccec65eaff536bd5bb2a0c5b8b0bdea47334.gif@48w_48h.webp",
                "tv_偷笑": "7f11e6f7f63e79112b833bd41fa13a83d7cd8474.gif@48w_48h.webp",
                "tv_抓狂":"a476b93ecd8e94ac3257323fd822f91cef212de2.gif@48w_48h.webp",
                "tv_黑人问号":"b609adf664be33224a9923262031165ae3e34cd2.gif@48w_48h.webp",
                "tv_困":"91c2bf34ecf842d7016c01d841db3d4074bd281f.gif@48w_48h.webp",
                "tv_打脸":"b0fad4856e59c1240e448437da3287bb5ce547e5.gif@48w_48h.webp",
                "tv_闭嘴":"a3fc5388b09e945be3f18fe23bfed5874a0285b7.gif@48w_48h.webp",
                "tv_鄙视":"293b5d459e6264ecf314d20937a936fa672ccd1e.gif@48w_48h.webp",
                "tv_腼腆":"30984e8264324f901d19bea85dada7103b695534.gif@48w_48h.webp",
                "tv_馋":"2525c5703c594e5f0752f68db8948773caebde47.gif@48w_48h.webp",
                "tv_可爱":"f92d20f76258bc5f33fc9d7c5e2a1d41fef19a7c.gif@48w_48h.webp",
                "tv_发财":"76131e52c9b033681b4c896c6024d29ef7ec7ec2.gif@48w_48h.webp",
                "tv_生病":"beb94829fe04f1a41bd6ca611e1f6ca9ca169afa.gif@48w_48h.webp",
                "tv_流鼻血":"8ef473f74a849420da712487b2f56ecca1f695f5.gif@48w_48h.webp",
                "tv_尴尬":"e0b84ef5ee3e5b8978e584c7c5a6550c51d15f84.gif@48w_48h.webp",
                "tv_大佬":"14ca0c05382b8741940942b2430b7a8d55c02f7e.gif@48w_48h.webp",
                "tv_流泪":"7e71cde7858f0cd50d74b0264aa26db612a8a167.png@48w_48h.webp",
                "tv_冷漠":"b9cbc755c2b3ee43be07ca13de84e5b699a3f101.png@48w_48h.webp",
                "tv_皱眉":"72ccad6679fea0d14cce648b4d818e09b8ffea2d.png@48w_48h.webp",
                "tv_鬼脸":"0ffbbddf8a94d124ca2f54b360bbc04feb6bbfea.png@48w_48h.webp",
                "tv_调侃":"4bc022533ef31544ca0d72c12c808cf4a1cce3e3.png@48w_48h.webp",
                "tv_目瞪口呆":"0b8cb81a68de5d5365212c99375e7ace3e7891b7.png@48w_48h.webp",
            },

            master: "8c9b6d6637904da62d74d019cc6982de",
            friends: "0188229a9cfc284176ea9135cb9514cc",
            tagMeta: ["博主","友人","访客"],
            visitor: true // 阅读量统计
          }
        )
        new Valine(options);
        Fluid.utils.waitElementVisible('#valine .vcontent', () => {
          var imgSelector = '#valine .vcontent img:not(.vemoji)';
          Fluid.plugins.imageCaption(imgSelector);
          Fluid.plugins.fancyBox(imgSelector);
        })
      });
    });
  </script>
  <noscript>Please enable JavaScript to view the comments</noscript>


    </article>
  


          </article>
        </div>
      </div>
    </div>

    <div class="side-col d-none d-lg-block col-lg-2">
      <!-- 文章页面 - 右侧目录 -->

  <aside class="sidebar" style="margin-left: -1rem">
    <!-- 文章页面 - 右侧目录上方 -->
<div id="toc">
  <p class="toc-header">
    <i class="iconfont icon-list"></i>
    <span>目录</span>
  </p>
  <div class="toc-body" id="toc-body"></div>
</div>



  </aside>



    </div>
  </div>
</div>





  



  



  



  



  







    

    
      <a id="scroll-top-button" aria-label="TOP" href="#" role="button">
        <i class="iconfont icon-arrowup" aria-hidden="true"></i>
      </a>
    

    
      <!-- 博客 - 搜索框 -->
<div
  class="modal fade"
  id="modalSearch"
  tabindex="-1"
  role="dialog"
  aria-labelledby="ModalLabel"
  aria-hidden="true"
>
  <div class="modal-dialog modal-dialog-scrollable modal-lg" role="document">
    <div class="modal-content">
      <div class="modal-header text-center">
        <h4 class="modal-title w-100 font-weight-bold">
          搜索
        </h4>
        <button
          type="button"
          id="local-search-close"
          class="close"
          data-dismiss="modal"
          aria-label="Close"
        >
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <div class="modal-body mx-3">
        <div class="md-form mb-5">
          <input
            type="text"
            id="local-search-input"
            class="form-control validate"
          />
          <label data-error="x" data-success="v" for="local-search-input"
            >关键词</label
          >
        </div>
        <div class="list-group" id="local-search-result"></div>
      </div>
    </div>
  </div>
</div>

    

    
        <div class="modal fade" id="modalNotice" tabindex="-1" role="dialog" aria-hidden="true"
     style="font-family: 'Ma Shan Zheng', cursive; color: #ffffff;">
    <div class="modal-dialog modal-dialog-scrollable" role="document"
         style="font-family: 'Ma Shan Zheng', cursive;">
        <div class="modal-content" style="border-radius: 6px;">
            <!-- 公告头部 - 响应式设计 -->
            <div class="modal-header text-center"
                 style="padding: 1rem 1.5rem;border-bottom: 1px solid rgba(255,255,255,0.2)">
                <h4 class="modal-title w-100 font-weight-bold"
                    style="font-family: 'Microsoft YaHei', sans-serif;letter-spacing: 1px;text-shadow: 1px 1px 2px rgba(0,0,0,0.2);color: #ffffff;
                           font-size: 1.5rem; /* 默认PC端大小 */
                           /* 移动端适配 */
                           @media (max-width: 768px) {
                               font-size: 1.2rem;
                           }">
                    <div class="notice-title">
                        <i class="fas fa-bullhorn mr-2"> 围栏告示</i>
                    </div>
                    <small style="display: block; font-family: 'STKaiti', serif; font-size: 0.6em; color: #a0a0a0; margin-top: 3px;">
                        旧梦轻拾 · 谨识
                    </small>
                </h4>
            </div>

            <!-- 公告内容区 - 响应式设计 -->
            <div class="modal-body"
                 style="padding: 2rem; /* PC端 */
                        max-height: 70vh;
                        overflow-y: auto;
                        /* 移动端适配 */
                        @media (max-width: 768px) {
                            padding: 1rem;
                            max-height: 60vh;
                        }">
                <!-- 图片容器（响应式设计） -->
                <!--                <div class="announcement-hero"-->
                <!--                     style="margin-bottom: 2rem; /* PC端 */-->
                <!--                            /* 移动端适配 */-->
                <!--                            @media (max-width: 768px) {-->
                <!--                                margin-bottom: 1rem;-->
                <!--                            }">-->
                <!--                    <img src="http://blog.memory-life.icu/%E3%80%90%E5%93%B2%E9%A3%8E%E5%A3%81%E7%BA%B8%E3%80%91%E5%8A%A8%E6%BC%AB-%E5%A4%95%E9%98%B3%E9%93%81%E8%BD%A8.jpg"-->
                <!--                         alt="时光溯洄题图"-->
                <!--                         style="width: 100%; -->
                <!--                                max-height: 400px; /* PC端 */-->
                <!--                                object-fit: cover;-->
                <!--                                border-radius: 4px; -->
                <!--                                box-shadow: 0 2px 12px rgba(0,0,0,0.1);-->
                <!--                                /* 移动端适配 */-->
                <!--                                @media (max-width: 768px) {-->
                <!--                                    max-height: 30vh;-->
                <!--                                }"-->
                <!--                         loading="lazy">-->
                <!--                </div>-->

                <!-- 静态公告列表 - 响应式设计 -->
                <div class="announcement-list">
                    <div class="announcement-item"
                         style="margin-bottom: 2rem; /* PC端 */
                                padding: 2rem;
                                background: rgba(255,255,255,0.05);
                                border-radius: 8px;
                                /* 移动端适配 */
                                @media (max-width: 768px) {
                                    margin-bottom: 1rem;
                                    padding: 1rem;
                                }">
                        <h2 style="color: #d38532;
                                  font-weight: 600;
                                  font-size: 1.5rem; /* PC端 */
                                  margin-bottom: 1.2rem;
                                  letter-spacing: 0.5px;
                                  /* 移动端适配 */
                                  @media (max-width: 768px) {
                                      font-size: 1.2rem;
                                      margin-bottom: 1rem;
                                  }">
                            <i class="fas fa-calendar-check mr-2"></i>时光溯洄
                            <small style="display: block; font-size: 0.6em; color: #b8b8b8;text-align: right;">——
                                晨昏往事</small>
                        </h2>
                        <div style="color: #e0e0e0;
                                  line-height: 1.8; /* PC端 */
                                  font-size: 1.05rem;
                                  letter-spacing: 0.3px;
                                  /* 移动端适配 */
                                  @media (max-width: 768px) {
                                      line-height: 1.6;
                                      font-size: 0.95rem;
                                  }">
                            <!-- 内容保持不变 -->
                            <p style="margin-bottom: 1rem; text-indent: 2em;">你好。</p>
                            <!-- 其余段落内容... -->
                            <p style="margin-bottom: 1rem; text-indent: 2em;">
                                建站后的第813天，在百忙之中总算又能抽出时间来，对整个博客站点功能做整体的规划及优化完善。</p>
                            <p style="margin-bottom: 1rem; text-indent: 2em;">
                                在刚刚过去的几年时间里，往事皆以笔墨挥毫于时光素笺之上，数百天如一日，故事的书写从未间断过。</p>
                            <p style="margin-bottom: 1rem; text-indent: 2em; font-style: italic; color: #b8b8b8;">
                                时光悠悠，日月如流，过往的蹉跎岁月总在不经意间在心间回眸。</p>
                            <p style="margin-bottom: 1rem; text-indent: 2em; font-weight: 500; color: #ffffff;">
                                俯仰之间，轻舟已过万重山。</p>
                            <p style="margin-bottom: 1rem; text-indent: 2em; font-weight: 500; color: #ffffff;">
                                蹉跎之处，往事皆成云烟散。</p>
                            <p style="margin-bottom: 1rem; text-indent: 2em;">
                                这几年的时光过得太快了，好像过去这段岁月里的所有事情都发生在一瞬间。</p>
                            <p style="margin-bottom: 1rem; text-indent: 2em;">
                                这几年的时光同样太久了，久到那些时日里仿佛囊括了自己的整个前半生。</p>
                            <p style="margin-bottom: 0; text-align: right; font-size: 0.95rem; color: #a0a0a0;">——
                                八百余个昼夜，当时只道是地久天长，如今回望，不过浮光掠影间的一瞬。</p>
                        </div>
                    </div>

                    <!-- 第二个公告项 - 响应式设计 -->
                    <div class="announcement-item"
                         style="margin-bottom: 2rem; /* PC端 */
                                padding: 2rem;
                                background: rgba(255,255,255,0.05);
                                border-radius: 8px;
                                /* 移动端适配 */
                                @media (max-width: 768px) {
                                    margin-bottom: 1rem;
                                    padding: 1rem;
                                }">
                        <h2 style="color: #6cc70b;
                                  font-weight: 600;
                                  font-size: 1.5rem; /* PC端 */
                                  margin-bottom: 1.2rem;
                                  letter-spacing: 0.5px;
                                  /* 移动端适配 */
                                  @media (max-width: 768px) {
                                      font-size: 1.2rem;
                                      margin-bottom: 1rem;
                                  }">
                            <i class="fas fa-book-open mr-2"></i>墨痕新注
                            <small style="display: block; font-size: 0.6em; color: #b8b8b8;text-align: right;">——
                                待起之章</small>
                        </h2>
                        <div style="color: #e0e0e0;
                                  line-height: 1.8; /* PC端 */
                                  font-size: 1.05rem;
                                  letter-spacing: 0.3px;
                                  /* 移动端适配 */
                                  @media (max-width: 768px) {
                                      line-height: 1.6;
                                      font-size: 0.95rem;
                                  }">
                            <!-- 列表内容 - 响应式设计 -->
                            <ul style="padding-left: 1.8rem; /* PC端 */
                                      margin-bottom: 1.5rem;
                                      /* 移动端适配 */
                                      @media (max-width: 768px) {
                                          padding-left: 1.5rem;
                                          margin-bottom: 1.2rem;
                                      }">
                                <li style="margin-bottom: 0.8rem; /* PC端 */
                                         position: relative;
                                         list-style-type: none;
                                         /* 移动端适配 */
                                         @media (max-width: 768px) {
                                             margin-bottom: 0.6rem;
                                         }">
                                    <span style="position: absolute;
                                               left: -1.8rem; /* PC端 */
                                               color: #6cc70b;
                                               /* 移动端适配 */
                                               @media (max-width: 768px) {
                                                   left: -1.5rem;
                                               }">◆</span>
                                    <span style="font-weight: bolder;">溯源计划：</span>新增博文"溯源计划"，旨在用先进的数字技术留住过去的旧时光，让家族的记忆在数字云端生长发芽，全站博文数量已达90+。
                                </li>
                                <li style="margin-bottom: 0.8rem; /* PC端 */
                                         position: relative;
                                         list-style-type: none;
                                         /* 移动端适配 */
                                         @media (max-width: 768px) {
                                             margin-bottom: 0.6rem;
                                         }">
                                    <span style="position: absolute;
                                               left: -1.8rem; /* PC端 */
                                               color: #6cc70b;
                                               /* 移动端适配 */
                                               @media (max-width: 768px) {
                                                   left: -1.5rem;
                                               }">◆</span>
                                    <span style="font-weight: bolder;">围栏告示：</span>自去年夏天站点新增了“评论回复”功能后，至今时隔十余月，在芒种前夕本站久违地上线“围栏告示”功能，本公告栏会不定时更新，持续跟进记录最新站点功能调整日志，更多精彩内容请敬请期待。
                                </li>
                                <li style="margin-bottom: 0.8rem; /* PC端 */
                                         position: relative;
                                         list-style-type: none;
                                         /* 移动端适配 */
                                         @media (max-width: 768px) {
                                             margin-bottom: 0.6rem;
                                         }">
                                    <span style="position: absolute;
                                               left: -1.8rem; /* PC端 */
                                               color: #6cc70b;
                                               /* 移动端适配 */
                                               @media (max-width: 768px) {
                                                   left: -1.5rem;
                                               }">◆</span>
                                    <span style="font-weight: bolder;">图片查看：</span>最近几周时间里，考虑到图文流量费用收取问题，暂时关闭了七牛云对象存储私有空间访问权限，故博文内的图文无法正常预览，择日考虑开启访问权限。
                                </li>
                                <li style="margin-bottom: 0.8rem; /* PC端 */
                                         position: relative;
                                         list-style-type: none;
                                         /* 移动端适配 */
                                         @media (max-width: 768px) {
                                             margin-bottom: 0.6rem;
                                         }">
                                    <span style="position: absolute;
                                               left: -1.8rem; /* PC端 */
                                               color: #6cc70b;
                                               /* 移动端适配 */
                                               @media (max-width: 768px) {
                                                   left: -1.5rem;
                                               }">◆</span>
                                    <span style="font-weight: bolder;">壁纸下载：</span>后续计划实现壁纸下载功能，均为个人收集的共150+超高分辨率精美壁纸，提供在线预览以及下载功能。
                                </li>
                                <li style="margin-bottom: 0.8rem; /* PC端 */
                                         position: relative;
                                         list-style-type: none;
                                         /* 移动端适配 */
                                         @media (max-width: 768px) {
                                             margin-bottom: 0.6rem;
                                         }">
                                    <span style="position: absolute;
                                               left: -1.8rem; /* PC端 */
                                               color: #6cc70b;
                                               /* 移动端适配 */
                                               @media (max-width: 768px) {
                                                   left: -1.5rem;
                                               }">◆</span>
                                    <span style="font-weight: bolder;">阅读体验：</span>规划完善文章内分页功能，并提供“最近更新”的文章列表，计划收录更新率较高的文章，譬如：阳台日记、叙事之外、岁月如歌、游戏人生等等，尽可能多的提升在线浏览和阅读体验。
                                </li>
                                <li style="margin-bottom: 0.8rem; /* PC端 */
                                         position: relative;
                                         list-style-type: none;
                                         /* 移动端适配 */
                                         @media (max-width: 768px) {
                                             margin-bottom: 0.6rem;
                                         }">
                                    <span style="position: absolute;
                                               left: -1.8rem; /* PC端 */
                                               color: #6cc70b;
                                               /* 移动端适配 */
                                               @media (max-width: 768px) {
                                                   left: -1.5rem;
                                               }">◆</span>
                                    <span style="font-weight: bolder;">友链完善：</span>持续优化完善友链页面，整理归档个人常用的高质量网站合集，无偿分享给有缘人。
                                </li>
                                <li style="margin-bottom: 0.8rem; /* PC端 */
                                         position: relative;
                                         list-style-type: none;
                                         /* 移动端适配 */
                                         @media (max-width: 768px) {
                                             margin-bottom: 0.6rem;
                                         }">
                                    <span style="position: absolute;
                                               left: -1.8rem; /* PC端 */
                                               color: #6cc70b;
                                               /* 移动端适配 */
                                               @media (max-width: 768px) {
                                                   left: -1.5rem;
                                               }">◆</span>
                                    <span style="font-weight: bolder;">音乐餐厅：</span>历经十余小时不间断调研和尝试，本站成功上线”音乐餐厅”功能，目前仅收录了个人在QQ音乐平台积累的两份歌单，再匆忙也要记得点播一首喜欢的音乐，没有音乐熏陶的心灵终究是充满缺憾的。
                                </li>
                                <li style="margin-bottom: 0.8rem; /* PC端 */
                                         position: relative;
                                         list-style-type: none;
                                         /* 移动端适配 */
                                         @media (max-width: 768px) {
                                             margin-bottom: 0.6rem;
                                         }">
                                    <span style="position: absolute;
                                               left: -1.8rem; /* PC端 */
                                               color: #6cc70b;
                                               /* 移动端适配 */
                                               @media (max-width: 768px) {
                                                   left: -1.5rem;
                                               }">◆</span>
                                    <span style="font-weight: bolder;">三言两语：</span>每张照片都是时光的便签，随手一贴就记下了那天，本站结合Mamos实现并注入留言板功能，随缘记录那些藏在照片背后的故事。
                                </li>
                                <li style="margin-bottom: 0.8rem; /* PC端 */
                                         position: relative;
                                         list-style-type: none;
                                         /* 移动端适配 */
                                         @media (max-width: 768px) {
                                             margin-bottom: 0.6rem;
                                         }">
                                    <span style="position: absolute;
                                               left: -1.8rem; /* PC端 */
                                               color: #6cc70b;
                                               /* 移动端适配 */
                                               @media (max-width: 768px) {
                                                   left: -1.5rem;
                                               }">◆</span>
                                    <span style="font-weight: bolder;">旧梦轻拾：</span>更新全站博客文章所属分类，共设有代码锋芒、部署之道、旧梦轻拾、人间片刻等十余种分类。
                                </li>
                                <li style="margin-bottom: 0.8rem; /* PC端 */
                                         position: relative;
                                         list-style-type: none;
                                         /* 移动端适配 */
                                         @media (max-width: 768px) {
                                             margin-bottom: 0.6rem;
                                         }">
                                    <span style="position: absolute;
                                               left: -1.8rem; /* PC端 */
                                               color: #6cc70b;
                                               /* 移动端适配 */
                                               @media (max-width: 768px) {
                                                   left: -1.5rem;
                                               }">◆</span>
                                    <span style="font-weight: bolder;">方寸之间：</span>博客应用版发布，更便捷的阅读体验来了！现已正式推出独立的桌面应用程序与移动端应用程序，暂时通过网盘和代码库提供安装包。
                                </li>
                                <p style="margin-bottom: 0; text-align: right; font-size: 0.9rem; color: #8a8a8a;">
                                    此公告最后更新于：<span style="color: #6cc70b;">2025/09/30晚</span>
                                </p>
                            </ul>
                        </div>
                    </div>
                </div>
            </div>

            <!-- 公告页脚 - 响应式设计 -->
            <div class="modal-footer"
                 style="border-top: 1px solid rgba(255,255,255,0.2);
                        padding: 1rem 1.5rem; /* PC端 */
                        justify-content: space-between;
                        /* 移动端适配 */
                        @media (max-width: 768px) {
                            padding: 0.8rem;
                        }">
                <small style="color: #ffffff;
                            font-size: 0.9rem; /* PC端 */
                            /* 移动端适配 */
                            @media (max-width: 768px) {
                                font-size: 0.8rem;
                            }">
                    <i class="iconfont icon-pen"></i>
                    <i class="fas fa-info-circle mr-1"></i>芒种前夕 · 旅途第813天
                    · 2025/05/28
                </small>
                <button id="confirm-btn" type="button" class="btn btn-sm" data-dismiss="modal"
                        style="background: #a0a0a0;
                               color: #ffffff;
                               border-radius: 4px;
                               padding: 0.5rem 1.2rem; /* PC端 */
                               border: none;
                               font-size: 0.9rem;
                               /* 移动端适配 */
                               @media (max-width: 768px) {
                                   padding: 0.3rem 0.8rem;
                                   font-size: 0.85rem;
                               }">
                    <i class="fas fa-check mr-1" style="color: #ffffff;">心已阅</i>
                </button>
            </div>
        </div>
    </div>
</div>

<style>
  .notice-title {
    display: flex;
    align-items: center;
    white-space: nowrap;
  }

  .notice-title:before,
  .notice-title:after {
    content: "";
    flex: 1;
    height: 1px;
    background: #ddd; /* 横线颜色 */
    margin: 0 10px; /* 横线与文字的间距 */
  }
</style>


<style>
  /* 响应式模态框宽度 */
  @media (min-width: 992px) {
    #modalNotice .modal-dialog {
      max-width: 800px;
    }
  }

  @media (max-width: 991px) {
    #modalNotice .modal-dialog {
      margin: 0.5rem auto;
    }
  }
</style>

<script>
  // 页面加载完成后执行
  document.addEventListener('DOMContentLoaded', function () {
    // 检查是否首次访问
    if (!localStorage.getItem('hasShownPopup')) {
      // 动态加载notice.ejs内容
      fetch('_partials/notice.ejs')  // 替换为实际路径
        .then(response => response.text())
        .then(html => {
          // 插入到页面body末尾
          document.body.insertAdjacentHTML('beforeend', html);

          // 手动初始化Bootstrap模态框
          $('#modalNotice').modal('show');

          // 标记为已显示
          localStorage.setItem('hasShownPopup', 'true');

          // 监听关闭事件
          $('#modalNotice').on('hidden.bs.modal', function () {
            // 可选的后续处理
          });
        })
        .catch(error => {
          console.error('加载公告栏失败:', error);
          // 备用方案：显示简单弹窗
          const fallbackHTML = `
                <div class="modal-backdrop" style="/* 样式 */">
                    <div class="modal-content">/* 内容 */</div>
                </div>`;
          document.body.insertAdjacentHTML('beforeend', fallbackHTML);
        });
    }
  });
</script>

    

    
  </main>

  <footer>
    <!-- 博客 - 页脚 -->
<div class="footer-inner">
  
    <div class="footer-content">
       <a href="https://hexo.fluid-dev.com/docs/guide/" target="_blank" rel="nofollow noopener"> <span>Memory | 个人文档站点</span> </a>
<i class="iconfont icon-love"></i> <a href="https://hexo.fluid-dev.com/docs/guide/" target="_blank" rel="nofollow noopener"> <span>配置指南 | Hexo Fluid 用户手册</span> </a> 
    </div>
  

  

  
    <!-- 备案信 ICP for China -->
    <div class="beian">
  <span>
    <a href="http://beian.miit.gov.cn/" target="_blank" rel="nofollow noopener">
      京ICP证123456号
    </a>
  </span>
  
    
      <span>
        <a
          href="http://www.beian.gov.cn/portal/registerSystemInfo?recordcode=12345678"
          rel="nofollow noopener"
          class="beian-police"
          target="_blank"
        >
          
            <span style="visibility: hidden; width: 0">|</span>
            <img src="/blog/img/police_beian.png" alt="police-icon"/>
          
          <span>京公网安备12345678号</span>
        </a>
      </span>
    
  
</div>

  

  

</div>

<!-- 评论框美化 -->
<style>
    #comments .veditor{
        min-height: 20vh;
        background-image: url(http://blog.memory-life.icu/pathway0716.jpg);
        background-size: contain;
        background-repeat: no-repeat;
        background-position: right;
        background-color: rgba(255,255,255,0);
        resize: none;}
</style>

<script>
    //   自定义邮箱审核规则
    document.body.addEventListener('click', function(e) {
        if (e.target.classList.contains('vsubmit')) {
            const email = document.querySelector('input[type=email]');
            const nick = document.querySelector('input[name=nick]');
            const reg = /^[A-Za-z0-9\u4e00-\u9fa5]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/;
            if (!email.value || !nick.value || !reg.test(email.value)) {
                const str = `<div class="valert text-center"><div class="vtext">请填写正确的昵称和邮箱！</div></div>`;
                const vmark = document.querySelector('.vmark');
                vmark.innerHTML = str;
                vmark.style.display = 'block';
                setTimeout(function() {
                    vmark.style.display = 'none';
                    vmark.innerHTML = '';
                }, 2500);
            }
        }
    })
</script>



  </footer>

  <!-- Scripts -->
  
  <script  src="https://lib.baomitu.com/nprogress/0.2.0/nprogress.min.js" ></script>
  <link  rel="stylesheet" href="https://lib.baomitu.com/nprogress/0.2.0/nprogress.min.css" />

  <script>
    NProgress.configure({"showSpinner":false,"trickleSpeed":100})
    NProgress.start()
    window.addEventListener('load', function() {
      NProgress.done();
    })
  </script>


<script  src="https://lib.baomitu.com/jquery/3.6.0/jquery.min.js" ></script>
<script  src="https://lib.baomitu.com/twitter-bootstrap/4.6.1/js/bootstrap.min.js" ></script>
<script  src="/blog/js/events.js" ></script>
<script  src="/blog/js/plugins.js" ></script>


  <script  src="https://lib.baomitu.com/typed.js/2.0.12/typed.min.js" ></script>
  <script>
    (function (window, document) {
      var typing = Fluid.plugins.typing;
      var subtitle = document.getElementById('subtitle');
      if (!subtitle || !typing) {
        return;
      }
      var text = subtitle.getAttribute('data-typed-text');
      
        typing(text);
      
    })(window, document);
  </script>







  
<script>
  Fluid.utils.createScript('https://lib.baomitu.com/tocbot/4.18.2/tocbot.min.js', function() {
    var toc = jQuery('#toc');
    if (toc.length === 0 || !window.tocbot) { return; }
    var boardCtn = jQuery('#board-ctn');
    var boardTop = boardCtn.offset().top;

    window.tocbot.init(Object.assign({
      tocSelector     : '#toc-body',
      contentSelector : '.markdown-body',
      linkClass       : 'tocbot-link',
      activeLinkClass : 'tocbot-active-link',
      listClass       : 'tocbot-list',
      isCollapsedClass: 'tocbot-is-collapsed',
      collapsibleClass: 'tocbot-is-collapsible',
      scrollSmooth    : true,
      includeTitleTags: true,
      headingsOffset  : -boardTop,
    }, CONFIG.toc));
    if (toc.find('.toc-list-item').length > 0) {
      toc.css('visibility', 'visible');
    }

    Fluid.events.registerRefreshCallback(function() {
      if ('tocbot' in window) {
        tocbot.refresh();
        var toc = jQuery('#toc');
        if (toc.length === 0 || !tocbot) {
          return;
        }
        if (toc.find('.toc-list-item').length > 0) {
          toc.css('visibility', 'visible');
        }
      }
    });
  });
</script>


  <script src=https://lib.baomitu.com/clipboard.js/2.0.11/clipboard.min.js></script>

  <script>Fluid.plugins.codeWidget();</script>


  
<script>
  Fluid.utils.createScript('https://lib.baomitu.com/anchor-js/4.3.1/anchor.min.js', function() {
    window.anchors.options = {
      placement: CONFIG.anchorjs.placement,
      visible  : CONFIG.anchorjs.visible
    };
    if (CONFIG.anchorjs.icon) {
      window.anchors.options.icon = CONFIG.anchorjs.icon;
    }
    var el = (CONFIG.anchorjs.element || 'h1,h2,h3,h4,h5,h6').split(',');
    var res = [];
    for (var item of el) {
      res.push('.markdown-body > ' + item.trim());
    }
    if (CONFIG.anchorjs.placement === 'left') {
      window.anchors.options.class = 'anchorjs-link-left';
    }
    window.anchors.add(res.join(', '));

    Fluid.events.registerRefreshCallback(function() {
      if ('anchors' in window) {
        anchors.removeAll();
        var el = (CONFIG.anchorjs.element || 'h1,h2,h3,h4,h5,h6').split(',');
        var res = [];
        for (var item of el) {
          res.push('.markdown-body > ' + item.trim());
        }
        if (CONFIG.anchorjs.placement === 'left') {
          anchors.options.class = 'anchorjs-link-left';
        }
        anchors.add(res.join(', '));
      }
    });
  });
</script>


  
<script>
  Fluid.utils.createScript('https://lib.baomitu.com/fancybox/3.5.7/jquery.fancybox.min.js', function() {
    Fluid.plugins.fancyBox();
  });
</script>


  <script>Fluid.plugins.imageCaption();</script>

  <script  src="/blog/js/local-search.js" ></script>

  <script defer src="/blog/js/leancloud.js" ></script>




    
<script src="https://cdn.jsdelivr.net/npm/aplayer@1.10.1/dist/APlayer.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/meting@2/dist/Meting.min.js"></script>



<!-- 主题的启动项，将它保持在最底部 -->
<!-- the boot of the theme, keep it at the bottom -->
<script  src="/blog/js/boot.js" ></script>


  

  <noscript>
    <div class="noscript-warning">博客在允许 JavaScript 运行的环境下浏览效果更佳</div>
  </noscript>
</body>
</html>
